blob: 59e79759b011e09e2f732e2b6ad99978df1deb0a [file] [log] [blame]
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001/*
2 * Copyright (c) 2013-2015 The Linux Foundation. All rights reserved.
3 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21
22/*
23 * This file was originally distributed by Qualcomm Atheros, Inc.
24 * under proprietary terms before Copyright ownership was assigned
25 * to the Linux Foundation.
26 */
27
28/**
29 * DOC: wma_power.c
30 * This file contains powersave related functions.
31 */
32
33/* Header files */
34
35#include "wma.h"
36#include "wma_api.h"
37#include "cds_api.h"
38#include "wmi_unified_api.h"
39#include "wlan_qct_sys.h"
40#include "wni_api.h"
41#include "ani_global.h"
42#include "wmi_unified.h"
43#include "wni_cfg.h"
44#include "cfg_api.h"
45#include "ol_txrx_ctrl_api.h"
46#include "wlan_tgt_def_config.h"
47
48#include "cdf_nbuf.h"
49#include "cdf_types.h"
50#include "ol_txrx_api.h"
51#include "cdf_memory.h"
52#include "ol_txrx_types.h"
53#include "ol_txrx_peer_find.h"
54
55#include "wma_types.h"
56#include "lim_api.h"
57#include "lim_session_utils.h"
58
59#include "cds_utils.h"
60
61#if !defined(REMOVE_PKT_LOG)
62#include "pktlog_ac.h"
63#endif /* REMOVE_PKT_LOG */
64
65#include "dbglog_host.h"
66#include "csr_api.h"
67#include "ol_fw.h"
68
69#include "dfs.h"
70#include "wma_internal.h"
71
72/**
73 * wmi_unified_modem_power_state() - set modem power state to fw
74 * @wmi_handle: wmi handle
75 * @param_value: parameter value
76 *
77 * Return: 0 for success or error code
78 */
79static int
80wmi_unified_modem_power_state(wmi_unified_t wmi_handle, uint32_t param_value)
81{
82 int ret;
83 wmi_modem_power_state_cmd_param *cmd;
84 wmi_buf_t buf;
85 uint16_t len = sizeof(*cmd);
86
87 buf = wmi_buf_alloc(wmi_handle, len);
88 if (!buf) {
89 WMA_LOGE("%s:wmi_buf_alloc failed", __func__);
90 return -ENOMEM;
91 }
92 cmd = (wmi_modem_power_state_cmd_param *) wmi_buf_data(buf);
93 WMITLV_SET_HDR(&cmd->tlv_header,
94 WMITLV_TAG_STRUC_wmi_modem_power_state_cmd_param,
95 WMITLV_GET_STRUCT_TLVLEN
96 (wmi_modem_power_state_cmd_param));
97 cmd->modem_power_state = param_value;
98 WMA_LOGD("%s: Setting cmd->modem_power_state = %u", __func__,
99 param_value);
100 ret = wmi_unified_cmd_send(wmi_handle, buf, len,
101 WMI_MODEM_POWER_STATE_CMDID);
102 if (ret != EOK) {
103 WMA_LOGE("Failed to send notify cmd ret = %d", ret);
104 wmi_buf_free(buf);
105 }
106 return ret;
107}
108
109/**
110 * wmi_unified_set_sta_ps_param() - set sta power save parameter to fw
111 * @wmi_handle: wmi handle
112 * @vdev_id: vdev id
113 * @param: param
114 * @value: parameter value
115 *
116 * Return: 0 for success or error code.
117 */
118int32_t wmi_unified_set_sta_ps_param(wmi_unified_t wmi_handle,
119 uint32_t vdev_id, uint32_t param,
120 uint32_t value)
121{
122 wmi_sta_powersave_param_cmd_fixed_param *cmd;
123 wmi_buf_t buf;
124 int32_t len = sizeof(*cmd);
125 tp_wma_handle wma;
126 struct wma_txrx_node *iface;
127
128 wma = cds_get_context(CDF_MODULE_ID_WMA);
129 if (NULL == wma) {
130 WMA_LOGE("%s: wma is NULL", __func__);
131 return -EIO;
132 }
133 iface = &wma->interfaces[vdev_id];
134
135 WMA_LOGD("Set Sta Ps param vdevId %d Param %d val %d",
136 vdev_id, param, value);
137
138 buf = wmi_buf_alloc(wmi_handle, len);
139 if (!buf) {
140 WMA_LOGP("%s: Set Sta Ps param Mem Alloc Failed", __func__);
141 return -ENOMEM;
142 }
143
144 cmd = (wmi_sta_powersave_param_cmd_fixed_param *) wmi_buf_data(buf);
145 WMITLV_SET_HDR(&cmd->tlv_header,
146 WMITLV_TAG_STRUC_wmi_sta_powersave_param_cmd_fixed_param,
147 WMITLV_GET_STRUCT_TLVLEN
148 (wmi_sta_powersave_param_cmd_fixed_param));
149 cmd->vdev_id = vdev_id;
150 cmd->param = param;
151 cmd->value = value;
152
153 if (wmi_unified_cmd_send(wmi_handle, buf, len,
154 WMI_STA_POWERSAVE_PARAM_CMDID)) {
155 WMA_LOGE("Set Sta Ps param Failed vdevId %d Param %d val %d",
156 vdev_id, param, value);
157 cdf_nbuf_free(buf);
158 return -EIO;
159 }
160 /* Store the PS Status */
161 iface->ps_enabled = value ? true : false;
162 return 0;
163}
164
165#ifdef QCA_IBSS_SUPPORT
166/**
167 * wma_set_ibss_pwrsave_params() - set ibss power save parameter to fw
168 * @wma: wma handle
169 * @vdev_id: vdev id
170 *
171 * Return: 0 for success or error code.
172 */
173CDF_STATUS
174wma_set_ibss_pwrsave_params(tp_wma_handle wma, uint8_t vdev_id)
175{
176 int ret;
177
178 ret = wmi_unified_vdev_set_param_send(wma->wmi_handle, vdev_id,
179 WMI_VDEV_PARAM_ATIM_WINDOW_LENGTH,
180 wma->wma_ibss_power_save_params.atimWindowLength);
181 if (ret < 0) {
182 WMA_LOGE("Failed to set WMI_VDEV_PARAM_ATIM_WINDOW_LENGTH ret = %d",
183 ret);
184 return CDF_STATUS_E_FAILURE;
185 }
186
187 ret = wmi_unified_vdev_set_param_send(wma->wmi_handle, vdev_id,
188 WMI_VDEV_PARAM_IS_IBSS_POWER_SAVE_ALLOWED,
189 wma->wma_ibss_power_save_params.isPowerSaveAllowed);
190 if (ret < 0) {
191 WMA_LOGE("Failed, set WMI_VDEV_PARAM_IS_IBSS_POWER_SAVE_ALLOWED ret=%d",
192 ret);
193 return CDF_STATUS_E_FAILURE;
194 }
195
196 ret = wmi_unified_vdev_set_param_send(wma->wmi_handle, vdev_id,
197 WMI_VDEV_PARAM_IS_POWER_COLLAPSE_ALLOWED,
198 wma->wma_ibss_power_save_params.isPowerCollapseAllowed);
199 if (ret < 0) {
200 WMA_LOGE("Failed, set WMI_VDEV_PARAM_IS_POWER_COLLAPSE_ALLOWED ret=%d",
201 ret);
202 return CDF_STATUS_E_FAILURE;
203 }
204
205 ret = wmi_unified_vdev_set_param_send(wma->wmi_handle, vdev_id,
206 WMI_VDEV_PARAM_IS_AWAKE_ON_TXRX_ENABLED,
207 wma->wma_ibss_power_save_params.isAwakeonTxRxEnabled);
208 if (ret < 0) {
209 WMA_LOGE("Failed, set WMI_VDEV_PARAM_IS_AWAKE_ON_TXRX_ENABLED ret=%d",
210 ret);
211 return CDF_STATUS_E_FAILURE;
212 }
213
214 ret = wmi_unified_vdev_set_param_send(wma->wmi_handle, vdev_id,
215 WMI_VDEV_PARAM_INACTIVITY_CNT,
216 wma->wma_ibss_power_save_params.inactivityCount);
217 if (ret < 0) {
218 WMA_LOGE("Failed, set WMI_VDEV_PARAM_INACTIVITY_CNT ret=%d",
219 ret);
220 return CDF_STATUS_E_FAILURE;
221 }
222
223 ret = wmi_unified_vdev_set_param_send(wma->wmi_handle, vdev_id,
224 WMI_VDEV_PARAM_TXSP_END_INACTIVITY_TIME_MS,
225 wma->wma_ibss_power_save_params.txSPEndInactivityTime);
226 if (ret < 0) {
227 WMA_LOGE("Failed, set WMI_VDEV_PARAM_TXSP_END_INACTIVITY_TIME_MS ret=%d",
228 ret);
229 return CDF_STATUS_E_FAILURE;
230 }
231
232 ret = wmi_unified_vdev_set_param_send(wma->wmi_handle, vdev_id,
233 WMI_VDEV_PARAM_IBSS_PS_WARMUP_TIME_SECS,
234 wma->wma_ibss_power_save_params.ibssPsWarmupTime);
235 if (ret < 0) {
236 WMA_LOGE("Failed, set WMI_VDEV_PARAM_IBSS_PS_WARMUP_TIME_SECS ret=%d",
237 ret);
238 return CDF_STATUS_E_FAILURE;
239 }
240
241 ret = wmi_unified_vdev_set_param_send(wma->wmi_handle, vdev_id,
242 WMI_VDEV_PARAM_IBSS_PS_1RX_CHAIN_IN_ATIM_WINDOW_ENABLE,
243 wma->wma_ibss_power_save_params.ibssPs1RxChainInAtimEnable);
244 if (ret < 0) {
245 WMA_LOGE("Failed to set IBSS_PS_1RX_CHAIN_IN_ATIM_WINDOW_ENABLE ret=%d",
246 ret);
247 return CDF_STATUS_E_FAILURE;
248 }
249
250 return CDF_STATUS_SUCCESS;
251}
252#endif /* QCA_IBSS_SUPPORT */
253
254/**
255 * wmi_unified_set_ap_ps_param() - set ap powersave parameters
256 * @wma_ctx: wma context
257 * @vdev_id: vdev id
258 * @peer_addr: peer mac address
259 * @param: parameter
260 * @value: prameter value
261 *
262 * Return: 0 for success or error code
263 */
264static int32_t wmi_unified_set_ap_ps_param(void *wma_ctx, uint32_t vdev_id,
265 uint8_t *peer_addr, uint32_t param,
266 uint32_t value)
267{
268 tp_wma_handle wma_handle = (tp_wma_handle) wma_ctx;
269 wmi_ap_ps_peer_cmd_fixed_param *cmd;
270 wmi_buf_t buf;
271 int32_t err;
272
273 buf = wmi_buf_alloc(wma_handle->wmi_handle, sizeof(*cmd));
274 if (!buf) {
275 WMA_LOGE("Failed to allocate buffer to send set_ap_ps_param cmd");
276 return -ENOMEM;
277 }
278 cmd = (wmi_ap_ps_peer_cmd_fixed_param *) wmi_buf_data(buf);
279 WMITLV_SET_HDR(&cmd->tlv_header,
280 WMITLV_TAG_STRUC_wmi_ap_ps_peer_cmd_fixed_param,
281 WMITLV_GET_STRUCT_TLVLEN
282 (wmi_ap_ps_peer_cmd_fixed_param));
283 cmd->vdev_id = vdev_id;
284 WMI_CHAR_ARRAY_TO_MAC_ADDR(peer_addr, &cmd->peer_macaddr);
285 cmd->param = param;
286 cmd->value = value;
287 err = wmi_unified_cmd_send(wma_handle->wmi_handle, buf,
288 sizeof(*cmd), WMI_AP_PS_PEER_PARAM_CMDID);
289 if (err) {
290 WMA_LOGE("Failed to send set_ap_ps_param cmd");
291 cdf_mem_free(buf);
292 return -EIO;
293 }
294 return 0;
295}
296
297/**
298 * wma_set_ap_peer_uapsd() - set powersave parameters in ap mode to fw
299 * @wma: wma handle
300 * @vdev_id: vdev id
301 * @peer_addr: peer mac address
302 * @uapsd_value: uapsd value
303 * @max_sp: maximum service period
304 *
305 * Return: 0 for success or error code.
306 */
307int32_t wma_set_ap_peer_uapsd(tp_wma_handle wma, uint32_t vdev_id,
308 uint8_t *peer_addr, uint8_t uapsd_value,
309 uint8_t max_sp)
310{
311 uint32_t uapsd = 0;
312 uint32_t max_sp_len = 0;
313 int32_t ret = 0;
314
315 if (uapsd_value & UAPSD_VO_ENABLED) {
316 uapsd |= WMI_AP_PS_UAPSD_AC3_DELIVERY_EN |
317 WMI_AP_PS_UAPSD_AC3_TRIGGER_EN;
318 }
319
320 if (uapsd_value & UAPSD_VI_ENABLED) {
321 uapsd |= WMI_AP_PS_UAPSD_AC2_DELIVERY_EN |
322 WMI_AP_PS_UAPSD_AC2_TRIGGER_EN;
323 }
324
325 if (uapsd_value & UAPSD_BK_ENABLED) {
326 uapsd |= WMI_AP_PS_UAPSD_AC1_DELIVERY_EN |
327 WMI_AP_PS_UAPSD_AC1_TRIGGER_EN;
328 }
329
330 if (uapsd_value & UAPSD_BE_ENABLED) {
331 uapsd |= WMI_AP_PS_UAPSD_AC0_DELIVERY_EN |
332 WMI_AP_PS_UAPSD_AC0_TRIGGER_EN;
333 }
334
335 switch (max_sp) {
336 case UAPSD_MAX_SP_LEN_2:
337 max_sp_len = WMI_AP_PS_PEER_PARAM_MAX_SP_2;
338 break;
339 case UAPSD_MAX_SP_LEN_4:
340 max_sp_len = WMI_AP_PS_PEER_PARAM_MAX_SP_4;
341 break;
342 case UAPSD_MAX_SP_LEN_6:
343 max_sp_len = WMI_AP_PS_PEER_PARAM_MAX_SP_6;
344 break;
345 default:
346 max_sp_len = WMI_AP_PS_PEER_PARAM_MAX_SP_UNLIMITED;
347 break;
348 }
349
350 WMA_LOGD("Set WMI_AP_PS_PEER_PARAM_UAPSD 0x%x for %pM",
351 uapsd, peer_addr);
352
353 ret = wmi_unified_set_ap_ps_param(wma, vdev_id,
354 peer_addr,
355 WMI_AP_PS_PEER_PARAM_UAPSD, uapsd);
356 if (ret) {
357 WMA_LOGE("Failed to set WMI_AP_PS_PEER_PARAM_UAPSD for %pM",
358 peer_addr);
359 return ret;
360 }
361
362 WMA_LOGD("Set WMI_AP_PS_PEER_PARAM_MAX_SP 0x%x for %pM",
363 max_sp_len, peer_addr);
364
365 ret = wmi_unified_set_ap_ps_param(wma, vdev_id,
366 peer_addr,
367 WMI_AP_PS_PEER_PARAM_MAX_SP,
368 max_sp_len);
369 if (ret) {
370 WMA_LOGE("Failed to set WMI_AP_PS_PEER_PARAM_MAX_SP for %pM",
371 peer_addr);
372 return ret;
373 }
374 return 0;
375}
376
377/**
378 * wma_update_edca_params_for_ac() - to update per ac EDCA parameters
379 * @edca_param: EDCA parameters
380 * @wmm_param: wmm parameters
381 * @ac: access category
382 *
383 * Return: none
384 */
385void wma_update_edca_params_for_ac(tSirMacEdcaParamRecord *edca_param,
386 wmi_wmm_vparams *wmm_param, int ac)
387{
388#define WMA_WMM_EXPO_TO_VAL(val) ((1 << (val)) - 1)
389 wmm_param->cwmin = WMA_WMM_EXPO_TO_VAL(edca_param->cw.min);
390 wmm_param->cwmax = WMA_WMM_EXPO_TO_VAL(edca_param->cw.max);
391 wmm_param->aifs = edca_param->aci.aifsn;
392 wmm_param->txoplimit = edca_param->txoplimit;
393 wmm_param->acm = edca_param->aci.acm;
394
395 /* TODO: No ack is not present in EdcaParamRecord */
396 wmm_param->no_ack = 0;
397
398 WMA_LOGI("WMM PARAMS AC[%d]: AIFS %d Min %d Max %d TXOP %d ACM %d NOACK %d",
399 ac, wmm_param->aifs, wmm_param->cwmin, wmm_param->cwmax,
400 wmm_param->txoplimit, wmm_param->acm, wmm_param->no_ack);
401}
402
403/**
404 * wma_set_tx_power() - set tx power limit in fw
405 * @handle: wma handle
406 * @tx_pwr_params: tx power parameters
407 *
408 * Return: none
409 */
410void wma_set_tx_power(WMA_HANDLE handle,
411 tMaxTxPowerParams *tx_pwr_params)
412{
413 tp_wma_handle wma_handle = (tp_wma_handle) handle;
414 uint8_t vdev_id;
415 int ret = -1;
416 void *pdev;
417
418 if (tx_pwr_params->dev_mode == CDF_SAP_MODE ||
419 tx_pwr_params->dev_mode == CDF_P2P_GO_MODE) {
420 pdev = wma_find_vdev_by_addr(wma_handle,
421 tx_pwr_params->bssId, &vdev_id);
422 } else {
423 pdev = wma_find_vdev_by_bssid(wma_handle,
424 tx_pwr_params->bssId, &vdev_id);
425 }
426 if (!pdev) {
427 WMA_LOGE("vdev handle is invalid for %pM",
428 tx_pwr_params->bssId);
429 cdf_mem_free(tx_pwr_params);
430 return;
431 }
432
433 if (!(wma_handle->interfaces[vdev_id].vdev_up)) {
434 WMA_LOGE("%s: vdev id %d is not up for %pM", __func__, vdev_id,
435 tx_pwr_params->bssId);
436 cdf_mem_free(tx_pwr_params);
437 return;
438 }
439
440 if (tx_pwr_params->power == 0) {
441 /* set to default. Since the app does not care the tx power
442 * we keep the previous setting */
443 wma_handle->interfaces[vdev_id].tx_power = 0;
444 ret = 0;
445 goto end;
446 }
447 if (wma_handle->interfaces[vdev_id].max_tx_power != 0) {
448 /* make sure tx_power less than max_tx_power */
449 if (tx_pwr_params->power >
450 wma_handle->interfaces[vdev_id].max_tx_power) {
451 tx_pwr_params->power =
452 wma_handle->interfaces[vdev_id].max_tx_power;
453 }
454 }
455 if (wma_handle->interfaces[vdev_id].tx_power != tx_pwr_params->power) {
456
457 /* tx_power changed, Push the tx_power to FW */
458 WMA_LOGW("%s: Set TX power limit [WMI_VDEV_PARAM_TX_PWRLIMIT] to %d",
459 __func__, tx_pwr_params->power);
460 ret = wmi_unified_vdev_set_param_send(wma_handle->wmi_handle,
461 vdev_id,
462 WMI_VDEV_PARAM_TX_PWRLIMIT,
463 tx_pwr_params->power);
464 if (ret == 0)
465 wma_handle->interfaces[vdev_id].tx_power =
466 tx_pwr_params->power;
467 } else {
468 /* no tx_power change */
469 ret = 0;
470 }
471end:
472 cdf_mem_free(tx_pwr_params);
473 if (ret)
474 WMA_LOGE("Failed to set vdev param WMI_VDEV_PARAM_TX_PWRLIMIT");
475}
476
477/**
478 * wma_set_max_tx_power() - set max tx power limit in fw
479 * @handle: wma handle
480 * @tx_pwr_params: tx power parameters
481 *
482 * Return: none
483 */
484void wma_set_max_tx_power(WMA_HANDLE handle,
485 tMaxTxPowerParams *tx_pwr_params)
486{
487 tp_wma_handle wma_handle = (tp_wma_handle) handle;
488 uint8_t vdev_id;
489 int ret = -1;
490 void *pdev;
491 tPowerdBm prev_max_power;
492
493 pdev = wma_find_vdev_by_addr(wma_handle, tx_pwr_params->bssId, &vdev_id);
494 if (pdev == NULL) {
495 /* not in SAP array. Try the station/p2p array */
496 pdev = wma_find_vdev_by_bssid(wma_handle,
497 tx_pwr_params->bssId, &vdev_id);
498 }
499 if (!pdev) {
500 WMA_LOGE("vdev handle is invalid for %pM",
501 tx_pwr_params->bssId);
502 cdf_mem_free(tx_pwr_params);
503 return;
504 }
505
506 if (!(wma_handle->interfaces[vdev_id].vdev_up)) {
507 WMA_LOGE("%s: vdev id %d is not up", __func__, vdev_id);
508 cdf_mem_free(tx_pwr_params);
509 return;
510 }
511
512 if (wma_handle->interfaces[vdev_id].max_tx_power ==
513 tx_pwr_params->power) {
514 ret = 0;
515 goto end;
516 }
517 prev_max_power = wma_handle->interfaces[vdev_id].max_tx_power;
518 wma_handle->interfaces[vdev_id].max_tx_power = tx_pwr_params->power;
519 if (wma_handle->interfaces[vdev_id].max_tx_power == 0) {
520 ret = 0;
521 goto end;
522 }
523 WMA_LOGW("Set MAX TX power limit [WMI_VDEV_PARAM_TX_PWRLIMIT] to %d",
524 wma_handle->interfaces[vdev_id].max_tx_power);
525 ret = wmi_unified_vdev_set_param_send(wma_handle->wmi_handle, vdev_id,
526 WMI_VDEV_PARAM_TX_PWRLIMIT,
527 wma_handle->interfaces[vdev_id].max_tx_power);
528 if (ret == 0)
529 wma_handle->interfaces[vdev_id].tx_power =
530 wma_handle->interfaces[vdev_id].max_tx_power;
531 else
532 wma_handle->interfaces[vdev_id].max_tx_power = prev_max_power;
533end:
534 cdf_mem_free(tx_pwr_params);
535 if (ret)
536 WMA_LOGE("%s: Failed to set vdev param WMI_VDEV_PARAM_TX_PWRLIMIT",
537 __func__);
538}
539
540/**
541 * wmi_unified_set_sta_ps() - set sta powersave params in fw
542 * @handle: wma handle
543 * @vdev_id: vdev id
544 * @val: value
545 *
546 * Return: 0 for success or error code.
547 */
548int32_t wmi_unified_set_sta_ps(wmi_unified_t wmi_handle,
549 uint32_t vdev_id, uint8_t val)
550{
551 wmi_sta_powersave_mode_cmd_fixed_param *cmd;
552 wmi_buf_t buf;
553 int32_t len = sizeof(*cmd);
554
555 WMA_LOGD("Set Sta Mode Ps vdevId %d val %d", vdev_id, val);
556
557 buf = wmi_buf_alloc(wmi_handle, len);
558 if (!buf) {
559 WMA_LOGP("%s: Set Sta Mode Ps Mem Alloc Failed", __func__);
560 return -ENOMEM;
561 }
562 cmd = (wmi_sta_powersave_mode_cmd_fixed_param *) wmi_buf_data(buf);
563 WMITLV_SET_HDR(&cmd->tlv_header,
564 WMITLV_TAG_STRUC_wmi_sta_powersave_mode_cmd_fixed_param,
565 WMITLV_GET_STRUCT_TLVLEN
566 (wmi_sta_powersave_mode_cmd_fixed_param));
567 cmd->vdev_id = vdev_id;
568 if (val)
569 cmd->sta_ps_mode = WMI_STA_PS_MODE_ENABLED;
570 else
571 cmd->sta_ps_mode = WMI_STA_PS_MODE_DISABLED;
572
573 if (wmi_unified_cmd_send(wmi_handle, buf, len,
574 WMI_STA_POWERSAVE_MODE_CMDID)) {
575 WMA_LOGE("Set Sta Mode Ps Failed vdevId %d val %d",
576 vdev_id, val);
577 cdf_nbuf_free(buf);
578 return -EIO;
579 }
580 return 0;
581}
582
583/**
584 * wma_get_uapsd_mask() - get uapsd mask based on uapsd parameters
585 * @uapsd_params: uapsed parameters
586 *
587 * Return: uapsd mask
588 */
589static inline uint32_t wma_get_uapsd_mask(tpUapsd_Params uapsd_params)
590{
591 uint32_t uapsd_val = 0;
592
593 if (uapsd_params->beDeliveryEnabled)
594 uapsd_val |= WMI_STA_PS_UAPSD_AC0_DELIVERY_EN;
595
596 if (uapsd_params->beTriggerEnabled)
597 uapsd_val |= WMI_STA_PS_UAPSD_AC0_TRIGGER_EN;
598
599 if (uapsd_params->bkDeliveryEnabled)
600 uapsd_val |= WMI_STA_PS_UAPSD_AC1_DELIVERY_EN;
601
602 if (uapsd_params->bkTriggerEnabled)
603 uapsd_val |= WMI_STA_PS_UAPSD_AC1_TRIGGER_EN;
604
605 if (uapsd_params->viDeliveryEnabled)
606 uapsd_val |= WMI_STA_PS_UAPSD_AC2_DELIVERY_EN;
607
608 if (uapsd_params->viTriggerEnabled)
609 uapsd_val |= WMI_STA_PS_UAPSD_AC2_TRIGGER_EN;
610
611 if (uapsd_params->voDeliveryEnabled)
612 uapsd_val |= WMI_STA_PS_UAPSD_AC3_DELIVERY_EN;
613
614 if (uapsd_params->voTriggerEnabled)
615 uapsd_val |= WMI_STA_PS_UAPSD_AC3_TRIGGER_EN;
616
617 return uapsd_val;
618}
619
620/**
621 * wma_set_force_sleep() - set power save parameters to fw
622 * @wma: wma handle
623 * @vdev_id: vdev id
624 * @enable: enable/disable
625 * @qpower_config: qpower configuration
626 *
627 * Return: 0 for success or error code
628 */
629static int32_t wma_set_force_sleep(tp_wma_handle wma,
630 uint32_t vdev_id,
631 uint8_t enable,
632 enum powersave_qpower_mode qpower_config)
633{
634 int32_t ret;
635 uint32_t cfg_data_val = 0;
636 /* get mac to acess CFG data base */
637 struct sAniSirGlobal *mac = cds_get_context(CDF_MODULE_ID_PE);
638 uint32_t rx_wake_policy;
639 uint32_t tx_wake_threshold;
640 uint32_t pspoll_count;
641 uint32_t inactivity_time;
642 uint32_t psmode;
643
644 WMA_LOGD("Set Force Sleep vdevId %d val %d", vdev_id, enable);
645
646 if (NULL == mac) {
647 WMA_LOGE("%s: Unable to get PE context", __func__);
648 return -ENOMEM;
649 }
650
651 /* Set Tx/Rx Data InActivity Timeout */
652 if (wlan_cfg_get_int(mac, WNI_CFG_PS_DATA_INACTIVITY_TIMEOUT,
653 &cfg_data_val) != eSIR_SUCCESS) {
654 CDF_TRACE(CDF_MODULE_ID_WMA, CDF_TRACE_LEVEL_ERROR,
655 "Failed to get WNI_CFG_PS_DATA_INACTIVITY_TIMEOUT");
656 cfg_data_val = POWERSAVE_DEFAULT_INACTIVITY_TIME;
657 }
658 inactivity_time = (uint32_t) cfg_data_val;
659
660 if (enable) {
661 /* override normal configuration and force station asleep */
662 rx_wake_policy = WMI_STA_PS_RX_WAKE_POLICY_POLL_UAPSD;
663 tx_wake_threshold = WMI_STA_PS_TX_WAKE_THRESHOLD_NEVER;
664
665 if (wlan_cfg_get_int(mac, WNI_CFG_MAX_PS_POLL,
666 &cfg_data_val) != eSIR_SUCCESS) {
667 CDF_TRACE(CDF_MODULE_ID_WMA, CDF_TRACE_LEVEL_ERROR,
668 "Failed to get value for WNI_CFG_MAX_PS_POLL");
669 }
670 if (cfg_data_val)
671 pspoll_count = (uint32_t) cfg_data_val;
672 else
673 pspoll_count = WMA_DEFAULT_MAX_PSPOLL_BEFORE_WAKE;
674
675 psmode = WMI_STA_PS_MODE_ENABLED;
676 } else {
677 /* Ps Poll Wake Policy */
678 if (wlan_cfg_get_int(mac, WNI_CFG_MAX_PS_POLL,
679 &cfg_data_val) != eSIR_SUCCESS) {
680 CDF_TRACE(CDF_MODULE_ID_WMA, CDF_TRACE_LEVEL_ERROR,
681 "Failed to get value for WNI_CFG_MAX_PS_POLL");
682 }
683 if (cfg_data_val) {
684 /* Ps Poll is enabled */
685 rx_wake_policy = WMI_STA_PS_RX_WAKE_POLICY_POLL_UAPSD;
686 pspoll_count = (uint32_t) cfg_data_val;
687 tx_wake_threshold = WMI_STA_PS_TX_WAKE_THRESHOLD_NEVER;
688 } else {
689 rx_wake_policy = WMI_STA_PS_RX_WAKE_POLICY_WAKE;
690 pspoll_count = WMI_STA_PS_PSPOLL_COUNT_NO_MAX;
691 tx_wake_threshold = WMI_STA_PS_TX_WAKE_THRESHOLD_ALWAYS;
692 }
693 psmode = WMI_STA_PS_MODE_ENABLED;
694 }
695
696 /*
697 * QPower is enabled by default in Firmware
698 * So Disable QPower explicitly
699 */
700 ret = wmi_unified_set_sta_ps_param(wma->wmi_handle, vdev_id,
701 WMI_STA_PS_ENABLE_QPOWER,
702 qpower_config);
703 if (ret) {
704 WMA_LOGE("Disable QPower Failed vdevId %d", vdev_id);
705 return ret;
706 }
707 WMA_LOGD("QPower Disabled vdevId %d", vdev_id);
708
709 /* Set the Wake Policy to WMI_STA_PS_RX_WAKE_POLICY_POLL_UAPSD */
710 ret = wmi_unified_set_sta_ps_param(wma->wmi_handle, vdev_id,
711 WMI_STA_PS_PARAM_RX_WAKE_POLICY,
712 rx_wake_policy);
713
714 if (ret) {
715 WMA_LOGE("Setting wake policy Failed vdevId %d", vdev_id);
716 return ret;
717 }
718 WMA_LOGD("Setting wake policy to %d vdevId %d",
719 rx_wake_policy, vdev_id);
720
721 /* Set the Tx Wake Threshold */
722 ret = wmi_unified_set_sta_ps_param(wma->wmi_handle, vdev_id,
723 WMI_STA_PS_PARAM_TX_WAKE_THRESHOLD,
724 tx_wake_threshold);
725
726 if (ret) {
727 WMA_LOGE("Setting TxWake Threshold vdevId %d", vdev_id);
728 return ret;
729 }
730 WMA_LOGD("Setting TxWake Threshold to %d vdevId %d",
731 tx_wake_threshold, vdev_id);
732
733 /* Set the Ps Poll Count */
734 ret = wmi_unified_set_sta_ps_param(wma->wmi_handle, vdev_id,
735 WMI_STA_PS_PARAM_PSPOLL_COUNT,
736 pspoll_count);
737
738 if (ret) {
739 WMA_LOGE("Set Ps Poll Count Failed vdevId %d ps poll cnt %d",
740 vdev_id, pspoll_count);
741 return ret;
742 }
743 WMA_LOGD("Set Ps Poll Count vdevId %d ps poll cnt %d",
744 vdev_id, pspoll_count);
745
746 /* Set the Tx/Rx InActivity */
747 ret = wmi_unified_set_sta_ps_param(wma->wmi_handle, vdev_id,
748 WMI_STA_PS_PARAM_INACTIVITY_TIME,
749 inactivity_time);
750
751 if (ret) {
752 WMA_LOGE("Setting Tx/Rx InActivity Failed vdevId %d InAct %d",
753 vdev_id, inactivity_time);
754 return ret;
755 }
756 WMA_LOGD("Set Tx/Rx InActivity vdevId %d InAct %d",
757 vdev_id, inactivity_time);
758
759 /* Enable Sta Mode Power save */
760 ret = wmi_unified_set_sta_ps(wma->wmi_handle, vdev_id, true);
761
762 if (ret) {
763 WMA_LOGE("Enable Sta Mode Ps Failed vdevId %d", vdev_id);
764 return ret;
765 }
766
767 /* Set Listen Interval */
768 if (wlan_cfg_get_int(mac, WNI_CFG_LISTEN_INTERVAL,
769 &cfg_data_val) != eSIR_SUCCESS) {
770 CDF_TRACE(CDF_MODULE_ID_WMA, CDF_TRACE_LEVEL_ERROR,
771 "Failed to get value for WNI_CFG_LISTEN_INTERVAL");
772 cfg_data_val = POWERSAVE_DEFAULT_LISTEN_INTERVAL;
773 }
774
775 ret = wmi_unified_vdev_set_param_send(wma->wmi_handle, vdev_id,
776 WMI_VDEV_PARAM_LISTEN_INTERVAL,
777 cfg_data_val);
778 if (ret) {
779 /* Even it fails continue Fw will take default LI */
780 WMA_LOGE("Failed to Set Listen Interval vdevId %d", vdev_id);
781 }
782 WMA_LOGD("Set Listen Interval vdevId %d Listen Intv %d",
783 vdev_id, cfg_data_val);
784 return 0;
785}
786
787/**
788 * wma_set_qpower_force_sleep() - set qpower params in fw
789 * @wma: wma handle
790 * @vdev_id: vdev id
791 * @enable: value
792 *
793 * Return: 0 for success or error code.
794 */
795int32_t wma_set_qpower_force_sleep(tp_wma_handle wma, uint32_t vdev_id,
796 uint8_t enable)
797{
798 int32_t ret;
799 uint32_t cfg_data_val = 0;
800 /* get mac to acess CFG data base */
801 struct sAniSirGlobal *mac = cds_get_context(CDF_MODULE_ID_PE);
802 uint32_t pspoll_count = WMA_DEFAULT_MAX_PSPOLL_BEFORE_WAKE;
803
804 WMA_LOGE("Set QPower Force(1)/Normal(0) Sleep vdevId %d val %d",
805 vdev_id, enable);
806
807 if (NULL == mac) {
808 WMA_LOGE("%s: Unable to get PE context", __func__);
809 return -ENOMEM;
810 }
811
812 /* Get Configured Ps Poll Count */
813 if (wlan_cfg_get_int(mac, WNI_CFG_MAX_PS_POLL,
814 &cfg_data_val) != eSIR_SUCCESS) {
815 CDF_TRACE(CDF_MODULE_ID_WMA, CDF_TRACE_LEVEL_ERROR,
816 "Failed to get value for WNI_CFG_MAX_PS_POLL");
817 }
818 if (cfg_data_val) {
819 pspoll_count = (uint32_t) cfg_data_val;
820 }
821
822 /* Enable QPower */
823 ret = wmi_unified_set_sta_ps_param(wma->wmi_handle, vdev_id,
824 WMI_STA_PS_ENABLE_QPOWER, 1);
825
826 if (ret) {
827 WMA_LOGE("Enable QPower Failed vdevId %d", vdev_id);
828 return ret;
829 }
830 WMA_LOGD("QPower Enabled vdevId %d", vdev_id);
831
832 /* Set the Wake Policy to WMI_STA_PS_RX_WAKE_POLICY_POLL_UAPSD */
833 ret = wmi_unified_set_sta_ps_param(wma->wmi_handle, vdev_id,
834 WMI_STA_PS_PARAM_RX_WAKE_POLICY,
835 WMI_STA_PS_RX_WAKE_POLICY_POLL_UAPSD);
836
837 if (ret) {
838 WMA_LOGE("Setting wake policy to pspoll/uapsd Failed vdevId %d",
839 vdev_id);
840 return ret;
841 }
842 WMA_LOGD("Wake policy set to to pspoll/uapsd vdevId %d", vdev_id);
843
844 if (enable) {
845 /* Set the Tx Wake Threshold */
846 ret = wmi_unified_set_sta_ps_param(wma->wmi_handle, vdev_id,
847 WMI_STA_PS_PARAM_TX_WAKE_THRESHOLD,
848 WMI_STA_PS_TX_WAKE_THRESHOLD_NEVER);
849
850 if (ret) {
851 WMA_LOGE("Setting TxWake Threshold vdevId %d", vdev_id);
852 return ret;
853 }
854 WMA_LOGD("TxWake Threshold set to TX_WAKE_THRESHOLD_NEVER %d",
855 vdev_id);
856 }
857
858 /* Set the QPower Ps Poll Count */
859 ret = wmi_unified_set_sta_ps_param(wma->wmi_handle, vdev_id,
860 WMI_STA_PS_PARAM_QPOWER_PSPOLL_COUNT,
861 pspoll_count);
862
863 if (ret) {
864 WMA_LOGE("Set QPower Ps Poll Count Failed vdevId %d ps poll cnt %d",
865 vdev_id, pspoll_count);
866 return ret;
867 }
868 WMA_LOGD("Set QPower Ps Poll Count vdevId %d ps poll cnt %d",
869 vdev_id, pspoll_count);
870
871 /* Enable Sta Mode Power save */
872 ret = wmi_unified_set_sta_ps(wma->wmi_handle, vdev_id, true);
873
874 if (ret) {
875 WMA_LOGE("Enable Sta Mode Ps Failed vdevId %d", vdev_id);
876 return ret;
877 }
878
879 /* Set Listen Interval */
880 if (wlan_cfg_get_int(mac, WNI_CFG_LISTEN_INTERVAL,
881 &cfg_data_val) != eSIR_SUCCESS) {
882 CDF_TRACE(CDF_MODULE_ID_WMA, CDF_TRACE_LEVEL_ERROR,
883 "Failed to get value for WNI_CFG_LISTEN_INTERVAL");
884 cfg_data_val = POWERSAVE_DEFAULT_LISTEN_INTERVAL;
885 }
886
887 ret = wmi_unified_vdev_set_param_send(wma->wmi_handle, vdev_id,
888 WMI_VDEV_PARAM_LISTEN_INTERVAL,
889 cfg_data_val);
890 if (ret) {
891 /* Even it fails continue Fw will take default LI */
892 WMA_LOGE("Failed to Set Listen Interval vdevId %d", vdev_id);
893 }
894 WMA_LOGD("Set Listen Interval vdevId %d Listen Intv %d",
895 vdev_id, cfg_data_val);
896 return 0;
897}
898
899/**
900 * wma_get_qpower_config() - get qpower configuration
901 * @wma: WMA handle
902 *
903 * Power Save Offload configuration:
904 * 0 -> Power save offload is disabled
905 * 1 -> Legacy Power save enabled + Deep sleep Disabled
906 * 2 -> QPower enabled + Deep sleep Disabled
907 * 3 -> Legacy Power save enabled + Deep sleep Enabled
908 * 4 -> QPower enabled + Deep sleep Enabled
909 * 5 -> Duty cycling QPower enabled
910 *
911 * Return: enum powersave_qpower_mode with below values
912 * QPOWER_DISABLED if QPOWER is disabled
913 * QPOWER_ENABLED if QPOWER is enabled
914 * QPOWER_DUTY_CYCLING if DUTY CYCLING QPOWER is enabled
915 */
916static enum powersave_qpower_mode wma_get_qpower_config(tp_wma_handle wma)
917{
918 switch (wma->powersave_mode) {
919 case PS_QPOWER_NODEEPSLEEP:
920 case PS_QPOWER_DEEPSLEEP:
921 WMA_LOGI("QPOWER is enabled in power save mode %d",
922 wma->powersave_mode);
923 return QPOWER_ENABLED;
924 case PS_DUTY_CYCLING_QPOWER:
925 WMA_LOGI("DUTY cycling QPOWER is enabled in power save mode %d",
926 wma->powersave_mode);
927 return QPOWER_DUTY_CYCLING;
928
929 default:
930 WMA_LOGI("QPOWER is disabled in power save mode %d",
931 wma->powersave_mode);
932 return QPOWER_DISABLED;
933 }
934}
935
936/**
937 * wma_enable_sta_ps_mode() - enable sta powersave params in fw
938 * @wma: wma handle
939 * @ps_req: power save request
940 *
941 * Return: none
942 */
943void wma_enable_sta_ps_mode(tp_wma_handle wma, tpEnablePsParams ps_req)
944{
945 uint32_t vdev_id = ps_req->sessionid;
946 int32_t ret;
947 enum powersave_qpower_mode qpower_config = wma_get_qpower_config(wma);
948 struct wma_txrx_node *iface = &wma->interfaces[vdev_id];
949 if (!iface->handle) {
950 WMA_LOGE("vdev id %d is not active", vdev_id);
951 return;
952 }
953 if (eSIR_ADDON_NOTHING == ps_req->psSetting) {
954 WMA_LOGD("Enable Sta Mode Ps vdevId %d", vdev_id);
955 ret = wmi_unified_set_sta_ps_param(wma->wmi_handle, vdev_id,
956 WMI_STA_PS_PARAM_UAPSD, 0);
957 if (ret) {
958 WMA_LOGE("Set Uapsd param 0 Failed vdevId %d", vdev_id);
959 return;
960 }
961
962 ret = wma_set_force_sleep(wma, vdev_id, false,
963 qpower_config);
964 if (ret) {
965 WMA_LOGE("Enable Sta Ps Failed vdevId %d", vdev_id);
966 return;
967 }
968 } else if (eSIR_ADDON_ENABLE_UAPSD == ps_req->psSetting) {
969 uint32_t uapsd_val = 0;
970 uapsd_val = wma_get_uapsd_mask(&ps_req->uapsdParams);
971
972 if (uapsd_val != iface->uapsd_cached_val) {
973 WMA_LOGD("Enable Uapsd vdevId %d Mask %d",
974 vdev_id, uapsd_val);
975 ret = wmi_unified_set_sta_ps_param(wma->wmi_handle,
976 vdev_id,
977 WMI_STA_PS_PARAM_UAPSD,
978 uapsd_val);
979 if (ret) {
980 WMA_LOGE("Enable Uapsd Failed vdevId %d",
981 vdev_id);
982 return;
983 }
984 /* Cache the Uapsd Mask */
985 iface->uapsd_cached_val = uapsd_val;
986 } else {
987 WMA_LOGD("Already Uapsd Enabled vdevId %d Mask %d",
988 vdev_id, uapsd_val);
989 }
990
991 WMA_LOGD("Enable Forced Sleep vdevId %d", vdev_id);
992 ret = wma_set_force_sleep(wma, vdev_id, true,
993 qpower_config);
994
995 if (ret) {
996 WMA_LOGE("Enable Forced Sleep Failed vdevId %d",
997 vdev_id);
998 return;
999 }
1000 }
1001 iface->dtimPeriod = ps_req->bcnDtimPeriod;
1002}
1003
1004/**
1005 * wma_disable_sta_ps_mode() - disable sta powersave params in fw
1006 * @wma: wma handle
1007 * @ps_req: power save request
1008 *
1009 * Return: none
1010 */
1011void wma_disable_sta_ps_mode(tp_wma_handle wma, tpDisablePsParams ps_req)
1012{
1013 int32_t ret;
1014 uint32_t vdev_id = ps_req->sessionid;
1015
1016 WMA_LOGD("Disable Sta Mode Ps vdevId %d", vdev_id);
1017
1018 /* Disable Sta Mode Power save */
1019 ret = wmi_unified_set_sta_ps(wma->wmi_handle, vdev_id, false);
1020 if (ret) {
1021 WMA_LOGE("Disable Sta Mode Ps Failed vdevId %d", vdev_id);
1022 return;
1023 }
1024
1025 /* Disable UAPSD incase if additional Req came */
1026 if (eSIR_ADDON_DISABLE_UAPSD == ps_req->psSetting) {
1027 WMA_LOGD("Disable Uapsd vdevId %d", vdev_id);
1028 ret = wmi_unified_set_sta_ps_param(wma->wmi_handle, vdev_id,
1029 WMI_STA_PS_PARAM_UAPSD, 0);
1030 if (ret) {
1031 WMA_LOGE("Disable Uapsd Failed vdevId %d", vdev_id);
1032 /*
1033 * Even this fails we can proceed as success
1034 * since we disabled powersave
1035 */
1036 }
1037 }
1038}
1039
1040/**
1041 * wma_enable_uapsd_mode() - enable uapsd mode in fw
1042 * @wma: wma handle
1043 * @ps_req: power save request
1044 *
1045 * Return: none
1046 */
1047void wma_enable_uapsd_mode(tp_wma_handle wma, tpEnableUapsdParams ps_req)
1048{
1049 int32_t ret;
1050 uint32_t vdev_id = ps_req->sessionid;
1051 uint32_t uapsd_val = 0;
1052 enum powersave_qpower_mode qpower_config = wma_get_qpower_config(wma);
1053
1054 /* Disable Sta Mode Power save */
1055 ret = wmi_unified_set_sta_ps(wma->wmi_handle, vdev_id, false);
1056 if (ret) {
1057 WMA_LOGE("Disable Sta Mode Ps Failed vdevId %d", vdev_id);
1058 return;
1059 }
1060
1061 uapsd_val = wma_get_uapsd_mask(&ps_req->uapsdParams);
1062
1063 WMA_LOGD("Enable Uapsd vdevId %d Mask %d", vdev_id, uapsd_val);
1064 ret = wmi_unified_set_sta_ps_param(wma->wmi_handle, vdev_id,
1065 WMI_STA_PS_PARAM_UAPSD, uapsd_val);
1066 if (ret) {
1067 WMA_LOGE("Enable Uapsd Failed vdevId %d", vdev_id);
1068 return;
1069 }
1070
1071 WMA_LOGD("Enable Forced Sleep vdevId %d", vdev_id);
1072 ret = wma_set_force_sleep(wma, vdev_id, true,
1073 qpower_config);
1074 if (ret) {
1075 WMA_LOGE("Enable Forced Sleep Failed vdevId %d", vdev_id);
1076 return;
1077 }
1078
1079}
1080
1081/**
1082 * wma_disable_uapsd_mode() - disable uapsd mode in fw
1083 * @wma: wma handle
1084 * @ps_req: power save request
1085 *
1086 * Return: none
1087 */
1088void wma_disable_uapsd_mode(tp_wma_handle wma,
1089 tpDisableUapsdParams ps_req)
1090{
1091 int32_t ret;
1092 uint32_t vdev_id = ps_req->sessionid;
1093 enum powersave_qpower_mode qpower_config = wma_get_qpower_config(wma);
1094
1095 WMA_LOGD("Disable Uapsd vdevId %d", vdev_id);
1096
1097 /* Disable Sta Mode Power save */
1098 ret = wmi_unified_set_sta_ps(wma->wmi_handle, vdev_id, false);
1099 if (ret) {
1100 WMA_LOGE("Disable Sta Mode Ps Failed vdevId %d", vdev_id);
1101 return;
1102 }
1103
1104 ret = wmi_unified_set_sta_ps_param(wma->wmi_handle, vdev_id,
1105 WMI_STA_PS_PARAM_UAPSD, 0);
1106 if (ret) {
1107 WMA_LOGE("Disable Uapsd Failed vdevId %d", vdev_id);
1108 return;
1109 }
1110
1111 /* Re enable Sta Mode Powersave with proper configuration */
1112 ret = wma_set_force_sleep(wma, vdev_id, false,
1113 qpower_config);
1114 if (ret) {
1115 WMA_LOGE("Disable Forced Sleep Failed vdevId %d", vdev_id);
1116 return;
1117 }
1118}
1119
1120/**
1121 * wmi_unified_set_sta_uapsd_auto_trig_cmd() - set uapsd auto trigger command
1122 * @wmi_handle: wma handle
1123 * @vdevid: vdev id
1124 * @peer_addr: peer mac address
1125 * @autoTriggerparam: auto trigger parameters
1126 * @num_ac: number of access category
1127 *
1128 * This function sets the trigger
1129 * uapsd params such as service interval, delay interval
1130 * and suspend interval which will be used by the firmware
1131 * to send trigger frames periodically when there is no
1132 * traffic on the transmit side.
1133 *
1134 * Return: 0 for success or error code.
1135 */
1136int32_t
1137wmi_unified_set_sta_uapsd_auto_trig_cmd(wmi_unified_t wmi_handle,
1138 uint32_t vdevid,
1139 uint8_t peer_addr[IEEE80211_ADDR_LEN],
1140 uint8_t *autoTriggerparam,
1141 uint32_t num_ac)
1142{
1143 wmi_sta_uapsd_auto_trig_cmd_fixed_param *cmd;
1144 int32_t ret;
1145 uint32_t param_len = num_ac * sizeof(wmi_sta_uapsd_auto_trig_param);
1146 uint32_t cmd_len = sizeof(*cmd) + param_len + WMI_TLV_HDR_SIZE;
1147 uint32_t i;
1148 wmi_buf_t buf;
1149 uint8_t *buf_ptr;
1150
1151 buf = wmi_buf_alloc(wmi_handle, cmd_len);
1152 if (!buf) {
1153 WMA_LOGE("%s:wmi_buf_alloc failed", __func__);
1154 return -ENOMEM;
1155 }
1156
1157 buf_ptr = (uint8_t *) wmi_buf_data(buf);
1158 cmd = (wmi_sta_uapsd_auto_trig_cmd_fixed_param *) buf_ptr;
1159 WMITLV_SET_HDR(&cmd->tlv_header,
1160 WMITLV_TAG_STRUC_wmi_sta_uapsd_auto_trig_cmd_fixed_param,
1161 WMITLV_GET_STRUCT_TLVLEN
1162 (wmi_sta_uapsd_auto_trig_cmd_fixed_param));
1163 cmd->vdev_id = vdevid;
1164 cmd->num_ac = num_ac;
1165 WMI_CHAR_ARRAY_TO_MAC_ADDR(peer_addr, &cmd->peer_macaddr);
1166
1167 /* TLV indicating array of structures to follow */
1168 buf_ptr += sizeof(*cmd);
1169 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, param_len);
1170
1171 buf_ptr += WMI_TLV_HDR_SIZE;
1172 cdf_mem_copy(buf_ptr, autoTriggerparam, param_len);
1173
1174 /*
1175 * Update tag and length for uapsd auto trigger params (this will take
1176 * care of updating tag and length if it is not pre-filled by caller).
1177 */
1178 for (i = 0; i < num_ac; i++) {
1179 WMITLV_SET_HDR((buf_ptr +
1180 (i * sizeof(wmi_sta_uapsd_auto_trig_param))),
1181 WMITLV_TAG_STRUC_wmi_sta_uapsd_auto_trig_param,
1182 WMITLV_GET_STRUCT_TLVLEN
1183 (wmi_sta_uapsd_auto_trig_param));
1184 }
1185
1186 ret = wmi_unified_cmd_send(wmi_handle, buf, cmd_len,
1187 WMI_STA_UAPSD_AUTO_TRIG_CMDID);
1188 if (ret != EOK) {
1189 WMA_LOGE("Failed to send set uapsd param ret = %d", ret);
1190 wmi_buf_free(buf);
1191 }
1192 return ret;
1193}
1194
1195/**
1196 * wma_trigger_uapsd_params() - set trigger uapsd parameter
1197 * @wmi_handle: wma handle
1198 * @vdev_id: vdev id
1199 * @trigger_uapsd_params: trigger uapsd parameters
1200 *
1201 * This function sets the trigger uapsd
1202 * params such as service interval, delay
1203 * interval and suspend interval which
1204 * will be used by the firmware to send
1205 * trigger frames periodically when there
1206 * is no traffic on the transmit side.
1207 *
1208 * Return: CDF_STATUS_SUCCESS for success or error code.
1209 */
1210CDF_STATUS wma_trigger_uapsd_params(tp_wma_handle wma_handle, uint32_t vdev_id,
1211 tp_wma_trigger_uapsd_params
1212 trigger_uapsd_params)
1213{
1214 int32_t ret;
1215 wmi_sta_uapsd_auto_trig_param uapsd_trigger_param;
1216
1217 WMA_LOGD("Trigger uapsd params vdev id %d", vdev_id);
1218
1219 WMA_LOGD("WMM AC %d User Priority %d SvcIntv %d DelIntv %d SusIntv %d",
1220 trigger_uapsd_params->wmm_ac,
1221 trigger_uapsd_params->user_priority,
1222 trigger_uapsd_params->service_interval,
1223 trigger_uapsd_params->delay_interval,
1224 trigger_uapsd_params->suspend_interval);
1225
1226 if (!WMI_SERVICE_IS_ENABLED(wma_handle->wmi_service_bitmap,
1227 WMI_STA_UAPSD_BASIC_AUTO_TRIG) ||
1228 !WMI_SERVICE_IS_ENABLED(wma_handle->wmi_service_bitmap,
1229 WMI_STA_UAPSD_VAR_AUTO_TRIG)) {
1230 WMA_LOGD("Trigger uapsd is not supported vdev id %d", vdev_id);
1231 return CDF_STATUS_SUCCESS;
1232 }
1233
1234 uapsd_trigger_param.wmm_ac = trigger_uapsd_params->wmm_ac;
1235 uapsd_trigger_param.user_priority = trigger_uapsd_params->user_priority;
1236 uapsd_trigger_param.service_interval =
1237 trigger_uapsd_params->service_interval;
1238 uapsd_trigger_param.suspend_interval =
1239 trigger_uapsd_params->suspend_interval;
1240 uapsd_trigger_param.delay_interval =
1241 trigger_uapsd_params->delay_interval;
1242
1243 ret = wmi_unified_set_sta_uapsd_auto_trig_cmd(wma_handle->wmi_handle,
1244 vdev_id, wma_handle->interfaces[vdev_id].bssid,
1245 (uint8_t *) (&uapsd_trigger_param), 1);
1246 if (ret) {
1247 WMA_LOGE("Fail to send uapsd param cmd for vdevid %d ret = %d",
1248 ret, vdev_id);
1249 return CDF_STATUS_E_FAILURE;
1250 }
1251 return CDF_STATUS_SUCCESS;
1252}
1253
1254/**
1255 * wma_disable_uapsd_per_ac() - disable uapsd per ac
1256 * @wmi_handle: wma handle
1257 * @vdev_id: vdev id
1258 * @ac: access category
1259 *
1260 * Return: CDF_STATUS_SUCCESS for success or error code.
1261 */
1262CDF_STATUS wma_disable_uapsd_per_ac(tp_wma_handle wma_handle,
1263 uint32_t vdev_id, enum uapsd_ac ac)
1264{
1265 int32_t ret;
1266 struct wma_txrx_node *iface = &wma_handle->interfaces[vdev_id];
1267 wmi_sta_uapsd_auto_trig_param uapsd_trigger_param;
1268 enum uapsd_up user_priority;
1269
1270 WMA_LOGD("Disable Uapsd per ac vdevId %d ac %d", vdev_id, ac);
1271
1272 switch (ac) {
1273 case UAPSD_VO:
1274 iface->uapsd_cached_val &=
1275 ~(WMI_STA_PS_UAPSD_AC3_DELIVERY_EN |
1276 WMI_STA_PS_UAPSD_AC3_TRIGGER_EN);
1277 user_priority = UAPSD_UP_VO;
1278 break;
1279 case UAPSD_VI:
1280 iface->uapsd_cached_val &=
1281 ~(WMI_STA_PS_UAPSD_AC2_DELIVERY_EN |
1282 WMI_STA_PS_UAPSD_AC2_TRIGGER_EN);
1283 user_priority = UAPSD_UP_VI;
1284 break;
1285 case UAPSD_BK:
1286 iface->uapsd_cached_val &=
1287 ~(WMI_STA_PS_UAPSD_AC1_DELIVERY_EN |
1288 WMI_STA_PS_UAPSD_AC1_TRIGGER_EN);
1289 user_priority = UAPSD_UP_BK;
1290 break;
1291 case UAPSD_BE:
1292 iface->uapsd_cached_val &=
1293 ~(WMI_STA_PS_UAPSD_AC0_DELIVERY_EN |
1294 WMI_STA_PS_UAPSD_AC0_TRIGGER_EN);
1295 user_priority = UAPSD_UP_BE;
1296 break;
1297 default:
1298 WMA_LOGE("Invalid AC vdevId %d ac %d", vdev_id, ac);
1299 return CDF_STATUS_E_FAILURE;
1300 }
1301
1302 /*
1303 * Disable Auto Trigger Functionality before
1304 * disabling uapsd for a particular AC
1305 */
1306 uapsd_trigger_param.wmm_ac = ac;
1307 uapsd_trigger_param.user_priority = user_priority;
1308 uapsd_trigger_param.service_interval = 0;
1309 uapsd_trigger_param.suspend_interval = 0;
1310 uapsd_trigger_param.delay_interval = 0;
1311
1312 ret = wmi_unified_set_sta_uapsd_auto_trig_cmd(wma_handle->wmi_handle,
1313 vdev_id, wma_handle->interfaces[vdev_id].bssid,
1314 (uint8_t *)(&uapsd_trigger_param), 1);
1315 if (ret) {
1316 WMA_LOGE("Fail to send auto trig cmd for vdevid %d ret = %d",
1317 ret, vdev_id);
1318 return CDF_STATUS_E_FAILURE;
1319 }
1320
1321 ret = wmi_unified_set_sta_ps_param(wma_handle->wmi_handle, vdev_id,
1322 WMI_STA_PS_PARAM_UAPSD,
1323 iface->uapsd_cached_val);
1324 if (ret) {
1325 WMA_LOGE("Disable Uapsd per ac Failed vdevId %d ac %d", vdev_id,
1326 ac);
1327 return CDF_STATUS_E_FAILURE;
1328 }
1329 WMA_LOGD("Disable Uapsd per ac vdevId %d val %d", vdev_id,
1330 iface->uapsd_cached_val);
1331 return CDF_STATUS_SUCCESS;
1332}
1333
1334/**
1335 * wma_get_temperature() - get pdev temperature req
1336 * @wmi_handle: wma handle
1337 *
1338 * Return: CDF_STATUS_SUCCESS for success or error code.
1339 */
1340CDF_STATUS wma_get_temperature(tp_wma_handle wma_handle)
1341{
1342 wmi_pdev_get_temperature_cmd_fixed_param *cmd;
1343 wmi_buf_t wmi_buf;
1344 uint32_t len = sizeof(wmi_pdev_get_temperature_cmd_fixed_param);
1345 uint8_t *buf_ptr;
1346
1347 if (!wma_handle) {
1348 WMA_LOGE(FL("WMA is closed, can not issue cmd"));
1349 return CDF_STATUS_E_INVAL;
1350 }
1351
1352 wmi_buf = wmi_buf_alloc(wma_handle->wmi_handle, len);
1353 if (!wmi_buf) {
1354 WMA_LOGE(FL("wmi_buf_alloc failed"));
1355 return CDF_STATUS_E_NOMEM;
1356 }
1357
1358 buf_ptr = (uint8_t *) wmi_buf_data(wmi_buf);
1359
1360 cmd = (wmi_pdev_get_temperature_cmd_fixed_param *) buf_ptr;
1361 WMITLV_SET_HDR(&cmd->tlv_header,
1362 WMITLV_TAG_STRUC_wmi_pdev_get_temperature_cmd_fixed_param,
1363 WMITLV_GET_STRUCT_TLVLEN
1364 (wmi_pdev_get_temperature_cmd_fixed_param));
1365
1366 if (wmi_unified_cmd_send(wma_handle->wmi_handle, wmi_buf, len,
1367 WMI_PDEV_GET_TEMPERATURE_CMDID)) {
1368 WMA_LOGE(FL("failed to send get temperature command"));
1369 wmi_buf_free(wmi_buf);
1370 return CDF_STATUS_E_FAILURE;
1371 }
1372 return CDF_STATUS_SUCCESS;
1373}
1374
1375/**
1376 * wma_pdev_temperature_evt_handler() - pdev temperature event handler
1377 * @handle: wma handle
1378 * @event: event buffer
1379 * @len : length
1380 *
1381 * Return: 0 for success or error code.
1382 */
1383int wma_pdev_temperature_evt_handler(void *handle, uint8_t *event,
1384 uint32_t len)
1385{
1386 CDF_STATUS cdf_status = CDF_STATUS_SUCCESS;
1387 cds_msg_t sme_msg = { 0 };
1388 WMI_PDEV_TEMPERATURE_EVENTID_param_tlvs *param_buf;
1389 wmi_pdev_temperature_event_fixed_param *wmi_event;
1390
1391 param_buf = (WMI_PDEV_TEMPERATURE_EVENTID_param_tlvs *) event;
1392 if (!param_buf) {
1393 WMA_LOGE("Invalid pdev_temperature event buffer");
1394 return -EINVAL;
1395 }
1396
1397 wmi_event = param_buf->fixed_param;
1398 WMA_LOGI(FL("temperature: %d"), wmi_event->value);
1399
1400 sme_msg.type = eWNI_SME_MSG_GET_TEMPERATURE_IND;
1401 sme_msg.bodyptr = NULL;
1402 sme_msg.bodyval = wmi_event->value;
1403
1404 cdf_status = cds_mq_post_message(CDF_MODULE_ID_SME, &sme_msg);
1405 if (!CDF_IS_STATUS_SUCCESS(cdf_status)) {
1406 WMA_LOGE(FL("Fail to post get temperature ind msg"));
1407 }
1408
1409 return 0;
1410}
1411
1412/**
1413 * wma_process_tx_power_limits() - sends the power limits for 2g/5g to firmware
1414 * @handle: wma handle
1415 * @ptxlim: power limit value
1416 *
1417 * Return: CDF_STATUS_SUCCESS for success or error code.
1418 */
1419CDF_STATUS wma_process_tx_power_limits(WMA_HANDLE handle,
1420 tSirTxPowerLimit *ptxlim)
1421{
1422 tp_wma_handle wma = (tp_wma_handle) handle;
1423 int32_t ret = 0;
1424 uint32_t txpower_params2g = 0;
1425 uint32_t txpower_params5g = 0;
1426
1427 if (!wma || !wma->wmi_handle) {
1428 WMA_LOGE("%s: WMA is closed, can not issue tx power limit",
1429 __func__);
1430 return CDF_STATUS_E_INVAL;
1431 }
1432 /* Set value and reason code for 2g and 5g power limit */
1433
1434 SET_PDEV_PARAM_TXPOWER_REASON(txpower_params2g,
1435 WMI_PDEV_PARAM_TXPOWER_REASON_SAR);
1436 SET_PDEV_PARAM_TXPOWER_VALUE(txpower_params2g, ptxlim->txPower2g);
1437
1438 SET_PDEV_PARAM_TXPOWER_REASON(txpower_params5g,
1439 WMI_PDEV_PARAM_TXPOWER_REASON_SAR);
1440 SET_PDEV_PARAM_TXPOWER_VALUE(txpower_params5g, ptxlim->txPower5g);
1441
1442 WMA_LOGD("%s: txpower2g: %x txpower5g: %x",
1443 __func__, txpower_params2g, txpower_params5g);
1444
1445 ret = wmi_unified_pdev_set_param(wma->wmi_handle,
1446 WMI_PDEV_PARAM_TXPOWER_LIMIT2G,
1447 txpower_params2g);
1448 if (ret) {
1449 WMA_LOGE("%s: Failed to set txpower 2g (%d)", __func__, ret);
1450 return CDF_STATUS_E_FAILURE;
1451 }
1452 ret = wmi_unified_pdev_set_param(wma->wmi_handle,
1453 WMI_PDEV_PARAM_TXPOWER_LIMIT5G,
1454 txpower_params5g);
1455 if (ret) {
1456 WMA_LOGE("%s: Failed to set txpower 5g (%d)", __func__, ret);
1457 return CDF_STATUS_E_FAILURE;
1458 }
1459 return CDF_STATUS_SUCCESS;
1460}
1461
1462/**
1463 * wma_add_p2p_ie() - add p2p IE
1464 * @frm: ptr where p2p ie needs to add
1465 *
1466 * Return: ptr after p2p ie
1467 */
1468uint8_t *wma_add_p2p_ie(uint8_t *frm)
1469{
1470 uint8_t wfa_oui[3] = WMA_P2P_WFA_OUI;
1471 struct p2p_ie *p2p_ie = (struct p2p_ie *)frm;
1472
1473 p2p_ie->p2p_id = WMA_P2P_IE_ID;
1474 p2p_ie->p2p_oui[0] = wfa_oui[0];
1475 p2p_ie->p2p_oui[1] = wfa_oui[1];
1476 p2p_ie->p2p_oui[2] = wfa_oui[2];
1477 p2p_ie->p2p_oui_type = WMA_P2P_WFA_VER;
1478 p2p_ie->p2p_len = 4;
1479 return frm + sizeof(struct p2p_ie);
1480}
1481
1482/**
1483 * wma_update_beacon_noa_ie() - update beacon ie
1484 * @bcn: beacon info
1485 * @new_noa_sub_ie_len: ie length
1486 *
1487 * Return: none
1488 */
1489static void wma_update_beacon_noa_ie(struct beacon_info *bcn,
1490 uint16_t new_noa_sub_ie_len)
1491{
1492 struct p2p_ie *p2p_ie;
1493 uint8_t *buf;
1494
1495 /* if there is nothing to add, just return */
1496 if (new_noa_sub_ie_len == 0) {
1497 if (bcn->noa_sub_ie_len && bcn->noa_ie) {
1498 WMA_LOGD("%s: NoA is present in previous beacon, "
1499 "but not present in swba event, "
1500 "So Reset the NoA", __func__);
1501 /* TODO: Assuming p2p noa ie is last ie in the beacon */
1502 cdf_mem_zero(bcn->noa_ie, (bcn->noa_sub_ie_len +
1503 sizeof(struct p2p_ie)));
1504 bcn->len -= (bcn->noa_sub_ie_len +
1505 sizeof(struct p2p_ie));
1506 bcn->noa_ie = NULL;
1507 bcn->noa_sub_ie_len = 0;
1508 }
1509 WMA_LOGD("%s: No need to update NoA", __func__);
1510 return;
1511 }
1512
1513 if (bcn->noa_sub_ie_len && bcn->noa_ie) {
1514 /* NoA present in previous beacon, update it */
1515 WMA_LOGD("%s: NoA present in previous beacon, "
1516 "update the NoA IE, bcn->len %u"
1517 "bcn->noa_sub_ie_len %u",
1518 __func__, bcn->len, bcn->noa_sub_ie_len);
1519 bcn->len -= (bcn->noa_sub_ie_len + sizeof(struct p2p_ie));
1520 cdf_mem_zero(bcn->noa_ie,
1521 (bcn->noa_sub_ie_len + sizeof(struct p2p_ie)));
1522 } else { /* NoA is not present in previous beacon */
1523 WMA_LOGD("%s: NoA not present in previous beacon, add it"
1524 "bcn->len %u", __func__, bcn->len);
1525 buf = cdf_nbuf_data(bcn->buf);
1526 bcn->noa_ie = buf + bcn->len;
1527 }
1528
1529 bcn->noa_sub_ie_len = new_noa_sub_ie_len;
1530 wma_add_p2p_ie(bcn->noa_ie);
1531 p2p_ie = (struct p2p_ie *)bcn->noa_ie;
1532 p2p_ie->p2p_len += new_noa_sub_ie_len;
1533 cdf_mem_copy((bcn->noa_ie + sizeof(struct p2p_ie)), bcn->noa_sub_ie,
1534 new_noa_sub_ie_len);
1535
1536 bcn->len += (new_noa_sub_ie_len + sizeof(struct p2p_ie));
1537 WMA_LOGI("%s: Updated beacon length with NoA Ie is %u",
1538 __func__, bcn->len);
1539}
1540
1541/**
1542 * wma_p2p_create_sub_ie_noa() - put p2p noa ie
1543 * @buf: buffer
1544 * @noa: noa element ie
1545 * @new_noa_sub_ie_len: ie length
1546 *
1547 * Return: none
1548 */
1549static void wma_p2p_create_sub_ie_noa(uint8_t *buf,
1550 struct p2p_sub_element_noa *noa,
1551 uint16_t *new_noa_sub_ie_len)
1552{
1553 uint8_t tmp_octet = 0;
1554 int i;
1555 uint8_t *buf_start = buf;
1556
1557 *buf++ = WMA_P2P_SUB_ELEMENT_NOA; /* sub-element id */
1558 ASSERT(noa->num_descriptors <= WMA_MAX_NOA_DESCRIPTORS);
1559
1560 /*
1561 * Length = (2 octets for Index and CTWin/Opp PS) and
1562 * (13 octets for each NOA Descriptors)
1563 */
1564 P2PIE_PUT_LE16(buf, WMA_NOA_IE_SIZE(noa->num_descriptors));
1565 buf += 2;
1566
1567 *buf++ = noa->index; /* Instance Index */
1568
1569 tmp_octet = noa->ctwindow & WMA_P2P_NOA_IE_CTWIN_MASK;
1570 if (noa->oppPS) {
1571 tmp_octet |= WMA_P2P_NOA_IE_OPP_PS_SET;
1572 }
1573 *buf++ = tmp_octet; /* Opp Ps and CTWin capabilities */
1574
1575 for (i = 0; i < noa->num_descriptors; i++) {
1576 ASSERT(noa->noa_descriptors[i].type_count != 0);
1577
1578 *buf++ = noa->noa_descriptors[i].type_count;
1579
1580 P2PIE_PUT_LE32(buf, noa->noa_descriptors[i].duration);
1581 buf += 4;
1582 P2PIE_PUT_LE32(buf, noa->noa_descriptors[i].interval);
1583 buf += 4;
1584 P2PIE_PUT_LE32(buf, noa->noa_descriptors[i].start_time);
1585 buf += 4;
1586 }
1587 *new_noa_sub_ie_len = (buf - buf_start);
1588}
1589
1590/**
1591 * wma_update_noa() - update noa params
1592 * @beacon: beacon info
1593 * @noa_ie: noa ie
1594 *
1595 * Return: none
1596 */
1597void wma_update_noa(struct beacon_info *beacon,
1598 struct p2p_sub_element_noa *noa_ie)
1599{
1600 uint16_t new_noa_sub_ie_len;
1601
1602 /* Call this function by holding the spinlock on beacon->lock */
1603
1604 if (noa_ie) {
1605 if ((noa_ie->ctwindow == 0) && (noa_ie->oppPS == 0) &&
1606 (noa_ie->num_descriptors == 0)) {
1607 /* NoA is not present */
1608 WMA_LOGD("%s: NoA is not present", __func__);
1609 new_noa_sub_ie_len = 0;
1610 } else {
1611 /* Create the binary blob containing NOA sub-IE */
1612 WMA_LOGD("%s: Create NOA sub ie", __func__);
1613 wma_p2p_create_sub_ie_noa(&beacon->noa_sub_ie[0],
1614 noa_ie, &new_noa_sub_ie_len);
1615 }
1616 } else {
1617 WMA_LOGD("%s: No need to add NOA", __func__);
1618 new_noa_sub_ie_len = 0; /* no NOA IE sub-attributes */
1619 }
1620
1621 wma_update_beacon_noa_ie(beacon, new_noa_sub_ie_len);
1622}
1623
1624/**
1625 * wma_update_probe_resp_noa() - update noa IE in probe response
1626 * @wma_handle: wma handle
1627 * @noa_ie: noa ie
1628 *
1629 * Return: none
1630 */
1631void wma_update_probe_resp_noa(tp_wma_handle wma_handle,
1632 struct p2p_sub_element_noa *noa_ie)
1633{
1634 tSirP2PNoaAttr *noa_attr =
1635 (tSirP2PNoaAttr *) cdf_mem_malloc(sizeof(tSirP2PNoaAttr));
1636 WMA_LOGD("Received update NoA event");
1637 if (!noa_attr) {
1638 WMA_LOGE("Failed to allocate memory for tSirP2PNoaAttr");
1639 return;
1640 }
1641
1642 cdf_mem_zero(noa_attr, sizeof(tSirP2PNoaAttr));
1643
1644 noa_attr->index = noa_ie->index;
1645 noa_attr->oppPsFlag = noa_ie->oppPS;
1646 noa_attr->ctWin = noa_ie->ctwindow;
1647 if (!noa_ie->num_descriptors) {
1648 WMA_LOGD("Zero NoA descriptors");
1649 } else {
1650 WMA_LOGD("%d NoA descriptors", noa_ie->num_descriptors);
1651 noa_attr->uNoa1IntervalCnt =
1652 noa_ie->noa_descriptors[0].type_count;
1653 noa_attr->uNoa1Duration = noa_ie->noa_descriptors[0].duration;
1654 noa_attr->uNoa1Interval = noa_ie->noa_descriptors[0].interval;
1655 noa_attr->uNoa1StartTime =
1656 noa_ie->noa_descriptors[0].start_time;
1657 if (noa_ie->num_descriptors > 1) {
1658 noa_attr->uNoa2IntervalCnt =
1659 noa_ie->noa_descriptors[1].type_count;
1660 noa_attr->uNoa2Duration =
1661 noa_ie->noa_descriptors[1].duration;
1662 noa_attr->uNoa2Interval =
1663 noa_ie->noa_descriptors[1].interval;
1664 noa_attr->uNoa2StartTime =
1665 noa_ie->noa_descriptors[1].start_time;
1666 }
1667 }
1668 WMA_LOGI("Sending SIR_HAL_P2P_NOA_ATTR_IND to LIM");
1669 wma_send_msg(wma_handle, SIR_HAL_P2P_NOA_ATTR_IND, (void *)noa_attr, 0);
1670}
1671
1672/**
1673 * wma_p2p_noa_event_handler() - p2p noa event handler
1674 * @handle: wma handle
1675 * @event: event data
1676 * @len: length
1677 *
1678 * Return: 0 for success or error code.
1679 */
1680int wma_p2p_noa_event_handler(void *handle, uint8_t *event,
1681 uint32_t len)
1682{
1683 tp_wma_handle wma = (tp_wma_handle) handle;
1684 WMI_P2P_NOA_EVENTID_param_tlvs *param_buf;
1685 wmi_p2p_noa_event_fixed_param *p2p_noa_event;
1686 uint8_t vdev_id, i;
1687 wmi_p2p_noa_info *p2p_noa_info;
1688 struct p2p_sub_element_noa noa_ie;
1689 uint8_t *buf_ptr;
1690 uint32_t descriptors;
1691
1692 param_buf = (WMI_P2P_NOA_EVENTID_param_tlvs *) event;
1693 if (!param_buf) {
1694 WMA_LOGE("Invalid P2P NoA event buffer");
1695 return -EINVAL;
1696 }
1697
1698 p2p_noa_event = param_buf->fixed_param;
1699 buf_ptr = (uint8_t *) p2p_noa_event;
1700 buf_ptr += sizeof(wmi_p2p_noa_event_fixed_param);
1701 p2p_noa_info = (wmi_p2p_noa_info *) (buf_ptr);
1702 vdev_id = p2p_noa_event->vdev_id;
1703
1704 if (WMI_UNIFIED_NOA_ATTR_IS_MODIFIED(p2p_noa_info)) {
1705
1706 cdf_mem_zero(&noa_ie, sizeof(noa_ie));
1707 noa_ie.index =
1708 (uint8_t) WMI_UNIFIED_NOA_ATTR_INDEX_GET(p2p_noa_info);
1709 noa_ie.oppPS =
1710 (uint8_t) WMI_UNIFIED_NOA_ATTR_OPP_PS_GET(p2p_noa_info);
1711 noa_ie.ctwindow =
1712 (uint8_t) WMI_UNIFIED_NOA_ATTR_CTWIN_GET(p2p_noa_info);
1713 descriptors = WMI_UNIFIED_NOA_ATTR_NUM_DESC_GET(p2p_noa_info);
1714 noa_ie.num_descriptors = (uint8_t) descriptors;
1715
1716 WMA_LOGI("%s: index %u, oppPs %u, ctwindow %u, "
1717 "num_descriptors = %u", __func__, noa_ie.index,
1718 noa_ie.oppPS, noa_ie.ctwindow, noa_ie.num_descriptors);
1719 for (i = 0; i < noa_ie.num_descriptors; i++) {
1720 noa_ie.noa_descriptors[i].type_count =
1721 (uint8_t) p2p_noa_info->noa_descriptors[i].
1722 type_count;
1723 noa_ie.noa_descriptors[i].duration =
1724 p2p_noa_info->noa_descriptors[i].duration;
1725 noa_ie.noa_descriptors[i].interval =
1726 p2p_noa_info->noa_descriptors[i].interval;
1727 noa_ie.noa_descriptors[i].start_time =
1728 p2p_noa_info->noa_descriptors[i].start_time;
1729 WMA_LOGI("%s: NoA descriptor[%d] type_count %u, "
1730 "duration %u, interval %u, start_time = %u",
1731 __func__, i,
1732 noa_ie.noa_descriptors[i].type_count,
1733 noa_ie.noa_descriptors[i].duration,
1734 noa_ie.noa_descriptors[i].interval,
1735 noa_ie.noa_descriptors[i].start_time);
1736 }
1737
1738 /* Send a msg to LIM to update the NoA IE in probe response
1739 * frames transmitted by the host */
1740 wma_update_probe_resp_noa(wma, &noa_ie);
1741 }
1742
1743 return 0;
1744}
1745
1746/**
1747 * wma_set_p2pgo_noa_req() - send p2p go noa request to fw
1748 * @wma: wma handle
1749 * @noa: p2p power save parameters
1750 *
1751 * Return: none
1752 */
1753static void wma_set_p2pgo_noa_req(tp_wma_handle wma, tP2pPsParams *noa)
1754{
1755 wmi_p2p_set_noa_cmd_fixed_param *cmd;
1756 wmi_p2p_noa_descriptor *noa_discriptor;
1757 wmi_buf_t buf;
1758 uint8_t *buf_ptr;
1759 uint16_t len;
1760 int32_t status;
1761 uint32_t duration;
1762
1763 WMA_LOGD("%s: Enter", __func__);
1764 len = sizeof(*cmd) + WMI_TLV_HDR_SIZE + sizeof(*noa_discriptor);
1765 buf = wmi_buf_alloc(wma->wmi_handle, len);
1766 if (!buf) {
1767 WMA_LOGE("Failed to allocate memory");
1768 goto end;
1769 }
1770
1771 buf_ptr = (uint8_t *) wmi_buf_data(buf);
1772 cmd = (wmi_p2p_set_noa_cmd_fixed_param *) buf_ptr;
1773 WMITLV_SET_HDR(&cmd->tlv_header,
1774 WMITLV_TAG_STRUC_wmi_p2p_set_noa_cmd_fixed_param,
1775 WMITLV_GET_STRUCT_TLVLEN
1776 (wmi_p2p_set_noa_cmd_fixed_param));
1777 duration = (noa->count == 1) ? noa->single_noa_duration : noa->duration;
1778 cmd->vdev_id = noa->sessionId;
1779 cmd->enable = (duration) ? true : false;
1780 cmd->num_noa = 1;
1781
1782 WMITLV_SET_HDR((buf_ptr + sizeof(wmi_p2p_set_noa_cmd_fixed_param)),
1783 WMITLV_TAG_ARRAY_STRUC, sizeof(wmi_p2p_noa_descriptor));
1784 noa_discriptor = (wmi_p2p_noa_descriptor *) (buf_ptr +
1785 sizeof
1786 (wmi_p2p_set_noa_cmd_fixed_param)
1787 + WMI_TLV_HDR_SIZE);
1788 WMITLV_SET_HDR(&noa_discriptor->tlv_header,
1789 WMITLV_TAG_STRUC_wmi_p2p_noa_descriptor,
1790 WMITLV_GET_STRUCT_TLVLEN(wmi_p2p_noa_descriptor));
1791 noa_discriptor->type_count = noa->count;
1792 noa_discriptor->duration = duration;
1793 noa_discriptor->interval = noa->interval;
1794 noa_discriptor->start_time = 0;
1795
1796 WMA_LOGI("SET P2P GO NOA:vdev_id:%d count:%d duration:%d interval:%d",
1797 cmd->vdev_id, noa->count, noa_discriptor->duration,
1798 noa->interval);
1799 status = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
1800 WMI_FWTEST_P2P_SET_NOA_PARAM_CMDID);
1801 if (status != EOK) {
1802 WMA_LOGE("Failed to send WMI_FWTEST_P2P_SET_NOA_PARAM_CMDID");
1803 wmi_buf_free(buf);
1804 }
1805
1806end:
1807 WMA_LOGD("%s: Exit", __func__);
1808}
1809
1810/**
1811 * wma_set_p2pgo_oppps_req() - send p2p go opp power save request to fw
1812 * @wma: wma handle
1813 * @noa: p2p opp power save parameters
1814 *
1815 * Return: none
1816 */
1817static void wma_set_p2pgo_oppps_req(tp_wma_handle wma, tP2pPsParams *oppps)
1818{
1819 wmi_p2p_set_oppps_cmd_fixed_param *cmd;
1820 wmi_buf_t buf;
1821 int32_t status;
1822
1823 WMA_LOGD("%s: Enter", __func__);
1824 buf = wmi_buf_alloc(wma->wmi_handle, sizeof(*cmd));
1825 if (!buf) {
1826 WMA_LOGE("Failed to allocate memory");
1827 goto end;
1828 }
1829
1830 cmd = (wmi_p2p_set_oppps_cmd_fixed_param *) wmi_buf_data(buf);
1831 WMITLV_SET_HDR(&cmd->tlv_header,
1832 WMITLV_TAG_STRUC_wmi_p2p_set_oppps_cmd_fixed_param,
1833 WMITLV_GET_STRUCT_TLVLEN
1834 (wmi_p2p_set_oppps_cmd_fixed_param));
1835 cmd->vdev_id = oppps->sessionId;
1836 if (oppps->ctWindow)
1837 WMI_UNIFIED_OPPPS_ATTR_ENABLED_SET(cmd);
1838
1839 WMI_UNIFIED_OPPPS_ATTR_CTWIN_SET(cmd, oppps->ctWindow);
1840 WMA_LOGI("SET P2P GO OPPPS:vdev_id:%d ctwindow:%d",
1841 cmd->vdev_id, oppps->ctWindow);
1842 status = wmi_unified_cmd_send(wma->wmi_handle, buf, sizeof(*cmd),
1843 WMI_P2P_SET_OPPPS_PARAM_CMDID);
1844 if (status != EOK) {
1845 WMA_LOGE("Failed to send WMI_P2P_SET_OPPPS_PARAM_CMDID");
1846 wmi_buf_free(buf);
1847 }
1848
1849end:
1850 WMA_LOGD("%s: Exit", __func__);
1851}
1852
1853/**
1854 * wma_process_set_p2pgo_noa_req() - process p2pgo noa request
1855 * @handle: wma handle
1856 * @ps_params: powersave params
1857 *
1858 * Return: none
1859 */
1860void wma_process_set_p2pgo_noa_req(tp_wma_handle wma,
1861 tP2pPsParams *ps_params)
1862{
1863 WMA_LOGD("%s: Enter", __func__);
1864 if (ps_params->opp_ps) {
1865 wma_set_p2pgo_oppps_req(wma, ps_params);
1866 } else {
1867 wma_set_p2pgo_noa_req(wma, ps_params);
1868 }
1869
1870 WMA_LOGD("%s: Exit", __func__);
1871}
1872
1873/**
1874 * wma_process_set_mimops_req() - Set the received MiMo PS state to firmware
1875 * @handle: wma handle
1876 * @mimops: MIMO powersave params
1877 *
1878 * Return: none
1879 */
1880void wma_process_set_mimops_req(tp_wma_handle wma_handle,
1881 tSetMIMOPS *mimops)
1882{
1883 /* Translate to what firmware understands */
1884 if (mimops->htMIMOPSState == eSIR_HT_MIMO_PS_DYNAMIC)
1885 mimops->htMIMOPSState = WMI_PEER_MIMO_PS_DYNAMIC;
1886 else if (mimops->htMIMOPSState == eSIR_HT_MIMO_PS_STATIC)
1887 mimops->htMIMOPSState = WMI_PEER_MIMO_PS_STATIC;
1888 else if (mimops->htMIMOPSState == eSIR_HT_MIMO_PS_NO_LIMIT)
1889 mimops->htMIMOPSState = WMI_PEER_MIMO_PS_NONE;
1890
1891 WMA_LOGD("%s: htMIMOPSState = %d, sessionId = %d \
1892 peerMac <%02x:%02x:%02x:%02x:%02x:%02x>", __func__,
1893 mimops->htMIMOPSState, mimops->sessionId, mimops->peerMac[0],
1894 mimops->peerMac[1], mimops->peerMac[2], mimops->peerMac[3],
1895 mimops->peerMac[4], mimops->peerMac[5]);
1896
1897 wma_set_peer_param(wma_handle, mimops->peerMac,
1898 WMI_PEER_MIMO_PS_STATE, mimops->htMIMOPSState,
1899 mimops->sessionId);
1900}
1901
1902/**
1903 * wma_set_mimops() - set MIMO powersave
1904 * @handle: wma handle
1905 * @vdev_id: vdev id
1906 * @value: value
1907 *
1908 * Return: CDF_STATUS_SUCCESS for success or error code.
1909 */
1910CDF_STATUS wma_set_mimops(tp_wma_handle wma, uint8_t vdev_id, int value)
1911{
1912 int ret = CDF_STATUS_SUCCESS;
1913 wmi_sta_smps_force_mode_cmd_fixed_param *cmd;
1914 wmi_buf_t buf;
1915 uint16_t len = sizeof(*cmd);
1916
1917 buf = wmi_buf_alloc(wma->wmi_handle, len);
1918 if (!buf) {
1919 WMA_LOGE("%s:wmi_buf_alloc failed", __func__);
1920 return -ENOMEM;
1921 }
1922 cmd = (wmi_sta_smps_force_mode_cmd_fixed_param *) wmi_buf_data(buf);
1923 WMITLV_SET_HDR(&cmd->tlv_header,
1924 WMITLV_TAG_STRUC_wmi_sta_smps_force_mode_cmd_fixed_param,
1925 WMITLV_GET_STRUCT_TLVLEN
1926 (wmi_sta_smps_force_mode_cmd_fixed_param));
1927
1928 cmd->vdev_id = vdev_id;
1929
1930 switch (value) {
1931 case 0:
1932 cmd->forced_mode = WMI_SMPS_FORCED_MODE_NONE;
1933 break;
1934 case 1:
1935 cmd->forced_mode = WMI_SMPS_FORCED_MODE_DISABLED;
1936 break;
1937 case 2:
1938 cmd->forced_mode = WMI_SMPS_FORCED_MODE_STATIC;
1939 break;
1940 case 3:
1941 cmd->forced_mode = WMI_SMPS_FORCED_MODE_DYNAMIC;
1942 break;
1943 default:
1944 WMA_LOGE("%s:INVALID Mimo PS CONFIG", __func__);
1945 return CDF_STATUS_E_FAILURE;
1946 }
1947
1948 WMA_LOGD("Setting vdev %d value = %u", vdev_id, value);
1949
1950 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
1951 WMI_STA_SMPS_FORCE_MODE_CMDID);
1952 if (ret < 0) {
1953 WMA_LOGE("Failed to send set Mimo PS ret = %d", ret);
1954 wmi_buf_free(buf);
1955 }
1956
1957 return ret;
1958}
1959
1960/**
1961 * wma_notify_modem_power_state() - notify modem power state
1962 * @wma_ptr: wma handle
1963 * @pReq: modem power state
1964 *
1965 * Return: CDF_STATUS_SUCCESS for success or error code.
1966 */
1967CDF_STATUS wma_notify_modem_power_state(void *wma_ptr,
1968 tSirModemPowerStateInd *pReq)
1969{
1970 int32_t ret;
1971 tp_wma_handle wma = (tp_wma_handle) wma_ptr;
1972
1973 WMA_LOGD("%s: WMA notify Modem Power State %d", __func__, pReq->param);
1974
1975 ret = wmi_unified_modem_power_state(wma->wmi_handle, pReq->param);
1976 if (ret) {
1977 WMA_LOGE("%s: Fail to notify Modem Power State %d",
1978 __func__, pReq->param);
1979 return CDF_STATUS_E_FAILURE;
1980 }
1981
1982 WMA_LOGD("Successfully notify Modem Power State %d", pReq->param);
1983 return CDF_STATUS_SUCCESS;
1984}
1985
1986/**
1987 * wma_set_idle_ps_config() - enable/disble Low Power Support(Pdev Specific)
1988 * @wma_ptr: wma handle
1989 * @idle_ps: idle powersave
1990 *
1991 * Return: CDF_STATUS_SUCCESS for success or error code.
1992 */
1993CDF_STATUS wma_set_idle_ps_config(void *wma_ptr, uint32_t idle_ps)
1994{
1995 int32_t ret;
1996 tp_wma_handle wma = (tp_wma_handle) wma_ptr;
1997
1998 WMA_LOGD("WMA Set Idle Ps Config [1:set 0:clear] val %d", idle_ps);
1999
2000 /* Set Idle Mode Power Save Config */
2001 ret = wmi_unified_pdev_set_param(wma->wmi_handle,
2002 WMI_PDEV_PARAM_IDLE_PS_CONFIG,
2003 idle_ps);
2004 if (ret) {
2005 WMA_LOGE("Fail to Set Idle Ps Config %d", idle_ps);
2006 return CDF_STATUS_E_FAILURE;
2007 }
2008
2009 WMA_LOGD("Successfully Set Idle Ps Config %d", idle_ps);
2010 return CDF_STATUS_SUCCESS;
2011}
2012
2013/**
2014 * wma_set_smps_params() - set smps params
2015 * @wma: wma handle
2016 * @vdev_id: vdev id
2017 * @value: value
2018 *
2019 * Return: CDF_STATUS_SUCCESS for success or error code.
2020 */
2021CDF_STATUS wma_set_smps_params(tp_wma_handle wma, uint8_t vdev_id,
2022 int value)
2023{
2024 int ret = CDF_STATUS_SUCCESS;
2025 wmi_sta_smps_param_cmd_fixed_param *cmd;
2026 wmi_buf_t buf;
2027 uint16_t len = sizeof(*cmd);
2028
2029 buf = wmi_buf_alloc(wma->wmi_handle, len);
2030 if (!buf) {
2031 WMA_LOGE("%s:wmi_buf_alloc failed", __func__);
2032 return -ENOMEM;
2033 }
2034 cmd = (wmi_sta_smps_param_cmd_fixed_param *) wmi_buf_data(buf);
2035 WMITLV_SET_HDR(&cmd->tlv_header,
2036 WMITLV_TAG_STRUC_wmi_sta_smps_param_cmd_fixed_param,
2037 WMITLV_GET_STRUCT_TLVLEN
2038 (wmi_sta_smps_param_cmd_fixed_param));
2039
2040 cmd->vdev_id = vdev_id;
2041 cmd->value = value & WMA_SMPS_MASK_LOWER_16BITS;
2042 cmd->param =
2043 (value >> WMA_SMPS_PARAM_VALUE_S) & WMA_SMPS_MASK_UPPER_3BITS;
2044
2045 WMA_LOGD("Setting vdev %d value = %x param %x", vdev_id, cmd->value,
2046 cmd->param);
2047
2048 ret = wmi_unified_cmd_send(wma->wmi_handle, buf, len,
2049 WMI_STA_SMPS_PARAM_CMDID);
2050 if (ret < 0) {
2051 WMA_LOGE("Failed to send set Mimo PS ret = %d", ret);
2052 wmi_buf_free(buf);
2053 }
2054
2055 return ret;
2056}
2057
2058/**
2059 * wma_set_vdev_suspend_dtim() - set suspend dtim parameters in fw
2060 * @wma: wma handle
2061 * @vdev_id: vdev id
2062 *
2063 * Return: none
2064 */
2065static void wma_set_vdev_suspend_dtim(tp_wma_handle wma, uint8_t vdev_id)
2066{
2067 struct wma_txrx_node *iface = &wma->interfaces[vdev_id];
2068 enum powersave_qpower_mode qpower_config = wma_get_qpower_config(wma);
2069
2070 if ((iface->type == WMI_VDEV_TYPE_STA) &&
2071 (iface->ps_enabled == true) &&
2072 (iface->dtimPeriod != 0)) {
2073 int32_t ret;
2074 uint32_t listen_interval;
2075 uint32_t max_mod_dtim;
2076
2077 if (wma->staDynamicDtim) {
2078 listen_interval = wma->staDynamicDtim;
2079 } else if ((wma->staModDtim) &&
2080 (wma->staMaxLIModDtim)) {
2081 /*
2082 * When the system is in suspend
2083 * (maximum beacon will be at 1s == 10)
2084 * If maxModulatedDTIM ((MAX_LI_VAL = 10) / AP_DTIM)
2085 * equal or larger than MDTIM
2086 * (configured in WCNSS_qcom_cfg.ini)
2087 * Set LI to MDTIM * AP_DTIM
2088 * If Dtim = 2 and Mdtim = 2 then LI is 4
2089 * Else
2090 * Set LI to maxModulatedDTIM * AP_DTIM
2091 */
2092 max_mod_dtim = wma->staMaxLIModDtim / iface->dtimPeriod;
2093 if (max_mod_dtim >= wma->staModDtim) {
2094 listen_interval =
2095 (wma->staModDtim * iface->dtimPeriod);
2096 } else {
2097 listen_interval =
2098 (max_mod_dtim * iface->dtimPeriod);
2099 }
2100 } else {
2101 return;
2102 }
2103
2104 ret = wmi_unified_vdev_set_param_send(wma->wmi_handle, vdev_id,
2105 WMI_VDEV_PARAM_LISTEN_INTERVAL,
2106 listen_interval);
2107 if (ret) {
2108 /* Even it fails continue Fw will take default LI */
2109 WMA_LOGE("Failed to Set Listen Interval vdevId %d",
2110 vdev_id);
2111 }
2112
2113 WMA_LOGD("Set Listen Interval vdevId %d Listen Intv %d",
2114 vdev_id, listen_interval);
2115
2116 if (qpower_config) {
2117 WMA_LOGD("disable Qpower in suspend mode!");
2118 ret = wmi_unified_set_sta_ps_param(wma->wmi_handle,
2119 vdev_id,
2120 WMI_STA_PS_ENABLE_QPOWER,
2121 0);
2122 if (ret)
2123 WMA_LOGE("Failed to disable Qpower in suspend mode!");
2124
2125 iface->ps_enabled = true;
2126 }
2127
2128 ret = wmi_unified_vdev_set_param_send(wma->wmi_handle, vdev_id,
2129 WMI_VDEV_PARAM_DTIM_POLICY,
2130 NORMAL_DTIM);
2131 if (ret)
2132 WMA_LOGE("Failed to Set to Normal DTIM vdevId %d",
2133 vdev_id);
2134
2135 /* Set it to Normal DTIM */
2136 iface->dtim_policy = NORMAL_DTIM;
2137 WMA_LOGD("Set DTIM Policy to Normal Dtim vdevId %d", vdev_id);
2138 }
2139}
2140
2141/**
2142 * wma_set_suspend_dtim() - set suspend dtim
2143 * @wma: wma handle
2144 *
2145 * Return: none
2146 */
2147void wma_set_suspend_dtim(tp_wma_handle wma)
2148{
2149 uint8_t i;
2150
2151 if (NULL == wma) {
2152 WMA_LOGE("%s: wma is NULL", __func__);
2153 return;
2154 }
2155
2156 for (i = 0; i < wma->max_bssid; i++) {
2157 if ((wma->interfaces[i].handle) &&
2158 (false == wma->interfaces[i].alt_modulated_dtim_enabled)) {
2159 wma_set_vdev_suspend_dtim(wma, i);
2160 }
2161 }
2162}
2163
2164/**
2165 * wma_set_vdev_resume_dtim() - set resume dtim parameters in fw
2166 * @wma: wma handle
2167 * @vdev_id: vdev id
2168 *
2169 * Return: none
2170 */
2171static void wma_set_vdev_resume_dtim(tp_wma_handle wma, uint8_t vdev_id)
2172{
2173 struct wma_txrx_node *iface = &wma->interfaces[vdev_id];
2174 enum powersave_qpower_mode qpower_config = wma_get_qpower_config(wma);
2175
2176 if ((iface->type == WMI_VDEV_TYPE_STA) &&
2177 (iface->ps_enabled == true) &&
2178 (iface->dtim_policy == NORMAL_DTIM)) {
2179 int32_t ret;
2180 uint32_t cfg_data_val = 0;
2181 /* get mac to acess CFG data base */
2182 struct sAniSirGlobal *mac = cds_get_context(CDF_MODULE_ID_PE);
2183 /* Set Listen Interval */
2184 if ((NULL == mac) || (wlan_cfg_get_int(mac,
2185 WNI_CFG_LISTEN_INTERVAL,
2186 &cfg_data_val) !=
2187 eSIR_SUCCESS)) {
2188 CDF_TRACE(CDF_MODULE_ID_WMA, CDF_TRACE_LEVEL_ERROR,
2189 "Failed to get value for listen interval");
2190 cfg_data_val = POWERSAVE_DEFAULT_LISTEN_INTERVAL;
2191 }
2192
2193 ret = wmi_unified_vdev_set_param_send(wma->wmi_handle, vdev_id,
2194 WMI_VDEV_PARAM_LISTEN_INTERVAL,
2195 cfg_data_val);
2196 if (ret) {
2197 /* Even it fails continue Fw will take default LI */
2198 WMA_LOGE("Failed to Set Listen Interval vdevId %d",
2199 vdev_id);
2200 }
2201
2202 WMA_LOGD("Set Listen Interval vdevId %d Listen Intv %d",
2203 vdev_id, cfg_data_val);
2204
2205 ret = wmi_unified_vdev_set_param_send(wma->wmi_handle, vdev_id,
2206 WMI_VDEV_PARAM_DTIM_POLICY,
2207 STICK_DTIM);
2208 if (ret) {
2209 /* Set it back to Stick DTIM */
2210 WMA_LOGE("Failed to Set to Stick DTIM vdevId %d",
2211 vdev_id);
2212 }
2213 iface->dtim_policy = STICK_DTIM;
2214 WMA_LOGD("Set DTIM Policy to Stick Dtim vdevId %d", vdev_id);
2215
2216 if (qpower_config) {
2217 WMA_LOGD("enable Qpower in resume mode!");
2218 ret = wmi_unified_set_sta_ps_param(wma->wmi_handle,
2219 vdev_id,
2220 WMI_STA_PS_ENABLE_QPOWER,
2221 1);
2222 if (ret)
2223 WMA_LOGE("Failed to enable Qpower in resume mode!");
2224 }
2225 }
2226}
2227
2228/**
2229 * wma_set_resume_dtim() - set resume dtim
2230 * @wma: wma handle
2231 *
2232 * Return: none
2233 */
2234void wma_set_resume_dtim(tp_wma_handle wma)
2235{
2236 uint8_t i;
2237
2238 if (NULL == wma) {
2239 WMA_LOGE("%s: wma is NULL", __func__);
2240 return;
2241 }
2242
2243 for (i = 0; i < wma->max_bssid; i++) {
2244 if ((wma->interfaces[i].handle) &&
2245 (false == wma->interfaces[i].alt_modulated_dtim_enabled)) {
2246 wma_set_vdev_resume_dtim(wma, i);
2247 }
2248 }
2249}
2250