1 /*
2 * Copyright (c) 2013-2021 The Linux Foundation. All rights reserved.
3 * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
4 *
5 * Permission to use, copy, modify, and/or distribute this software for
6 * any purpose with or without fee is hereby granted, provided that the
7 * above copyright notice and this permission notice appear in all
8 * copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
18 */
19
20 /**
21 * DOC: wma_power.c
22 * This file contains powersave related functions.
23 */
24
25 /* Header files */
26
27 #include "wma.h"
28 #include "wma_api.h"
29 #include "cds_api.h"
30 #include "wmi_unified_api.h"
31 #include "wlan_qct_sys.h"
32 #include "wni_api.h"
33 #include "ani_global.h"
34 #include "wmi_unified.h"
35 #include "wni_cfg.h"
36
37 #include "qdf_nbuf.h"
38 #include "qdf_types.h"
39 #include "qdf_mem.h"
40 #include "wma_types.h"
41 #include "lim_api.h"
42 #include "lim_session_utils.h"
43
44 #include "cds_utils.h"
45
46 #if !defined(REMOVE_PKT_LOG)
47 #include "pktlog_ac.h"
48 #endif /* REMOVE_PKT_LOG */
49
50 #include "dbglog_host.h"
51 #include "csr_api.h"
52 #include "ol_fw.h"
53
54 #include "wma_internal.h"
55 #include "wlan_pmo_ucfg_api.h"
56
57 /**
58 * wma_unified_modem_power_state() - set modem power state to fw
59 * @wmi_handle: wmi handle
60 * @param_value: parameter value
61 *
62 * Return: QDF_STATUS
63 */
64 static QDF_STATUS
wma_unified_modem_power_state(wmi_unified_t wmi_handle,uint32_t param_value)65 wma_unified_modem_power_state(wmi_unified_t wmi_handle, uint32_t param_value)
66 {
67 QDF_STATUS status;
68 wmi_modem_power_state_cmd_param *cmd;
69 wmi_buf_t buf;
70 uint16_t len = sizeof(*cmd);
71
72 buf = wmi_buf_alloc(wmi_handle, len);
73 if (!buf)
74 return -ENOMEM;
75
76 cmd = (wmi_modem_power_state_cmd_param *) wmi_buf_data(buf);
77 WMITLV_SET_HDR(&cmd->tlv_header,
78 WMITLV_TAG_STRUC_wmi_modem_power_state_cmd_param,
79 WMITLV_GET_STRUCT_TLVLEN
80 (wmi_modem_power_state_cmd_param));
81 cmd->modem_power_state = param_value;
82 wma_debug("Setting cmd->modem_power_state = %u", param_value);
83 status = wmi_unified_cmd_send(wmi_handle, buf, len,
84 WMI_MODEM_POWER_STATE_CMDID);
85 if (QDF_IS_STATUS_ERROR(status))
86 wmi_buf_free(buf);
87
88 return status;
89 }
90
91 /**
92 * wma_unified_set_sta_ps_param() - set sta power save parameter to fw
93 * @wmi_handle: wmi handle
94 * @vdev_id: vdev id
95 * @param: param
96 * @value: parameter value
97 *
98 * Return: QDF_STATUS_SUCCESS for success or error code
99 */
wma_unified_set_sta_ps_param(wmi_unified_t wmi_handle,uint32_t vdev_id,uint32_t param,uint32_t value)100 QDF_STATUS wma_unified_set_sta_ps_param(wmi_unified_t wmi_handle,
101 uint32_t vdev_id, uint32_t param,
102 uint32_t value)
103 {
104 tp_wma_handle wma;
105 struct wma_txrx_node *iface;
106 struct sta_ps_params sta_ps_param = {0};
107 QDF_STATUS status;
108
109 wma = cds_get_context(QDF_MODULE_ID_WMA);
110 if (!wma)
111 return QDF_STATUS_E_FAILURE;
112 if (!wma_is_vdev_valid(vdev_id))
113 return QDF_STATUS_E_INVAL;
114
115 wma_debug("Set Sta Ps param vdevId %d Param %d val %d",
116 vdev_id, param, value);
117 iface = &wma->interfaces[vdev_id];
118
119 sta_ps_param.vdev_id = vdev_id;
120 sta_ps_param.param_id = param;
121 sta_ps_param.value = value;
122 status = wmi_unified_sta_ps_cmd_send(wmi_handle, &sta_ps_param);
123 if (QDF_IS_STATUS_ERROR(status))
124 return status;
125
126 return status;
127 }
128
129 /**
130 * wma_set_ap_peer_uapsd() - set powersave parameters in ap mode to fw
131 * @wma: wma handle
132 * @vdev_id: vdev id
133 * @peer_addr: peer mac address
134 * @uapsd_value: uapsd value
135 * @max_sp: maximum service period
136 *
137 * Return: QDF_STATUS_SUCCESS for success or error code
138 */
wma_set_ap_peer_uapsd(tp_wma_handle wma,uint32_t vdev_id,uint8_t * peer_addr,uint8_t uapsd_value,uint8_t max_sp)139 QDF_STATUS wma_set_ap_peer_uapsd(tp_wma_handle wma, uint32_t vdev_id,
140 uint8_t *peer_addr, uint8_t uapsd_value,
141 uint8_t max_sp)
142 {
143 uint32_t uapsd = 0;
144 uint32_t max_sp_len = 0;
145 QDF_STATUS ret;
146 struct ap_ps_params param = {0};
147
148 if (uapsd_value & UAPSD_VO_ENABLED) {
149 uapsd |= WMI_AP_PS_UAPSD_AC3_DELIVERY_EN |
150 WMI_AP_PS_UAPSD_AC3_TRIGGER_EN;
151 }
152
153 if (uapsd_value & UAPSD_VI_ENABLED) {
154 uapsd |= WMI_AP_PS_UAPSD_AC2_DELIVERY_EN |
155 WMI_AP_PS_UAPSD_AC2_TRIGGER_EN;
156 }
157
158 if (uapsd_value & UAPSD_BK_ENABLED) {
159 uapsd |= WMI_AP_PS_UAPSD_AC1_DELIVERY_EN |
160 WMI_AP_PS_UAPSD_AC1_TRIGGER_EN;
161 }
162
163 if (uapsd_value & UAPSD_BE_ENABLED) {
164 uapsd |= WMI_AP_PS_UAPSD_AC0_DELIVERY_EN |
165 WMI_AP_PS_UAPSD_AC0_TRIGGER_EN;
166 }
167
168 switch (max_sp) {
169 case UAPSD_MAX_SP_LEN_2:
170 max_sp_len = WMI_AP_PS_PEER_PARAM_MAX_SP_2;
171 break;
172 case UAPSD_MAX_SP_LEN_4:
173 max_sp_len = WMI_AP_PS_PEER_PARAM_MAX_SP_4;
174 break;
175 case UAPSD_MAX_SP_LEN_6:
176 max_sp_len = WMI_AP_PS_PEER_PARAM_MAX_SP_6;
177 break;
178 default:
179 max_sp_len = WMI_AP_PS_PEER_PARAM_MAX_SP_UNLIMITED;
180 break;
181 }
182
183 wma_debug("Set WMI_AP_PS_PEER_PARAM_UAPSD 0x%x for "QDF_MAC_ADDR_FMT,
184 uapsd, QDF_MAC_ADDR_REF(peer_addr));
185 param.vdev_id = vdev_id;
186 param.param = WMI_AP_PS_PEER_PARAM_UAPSD;
187 param.value = uapsd;
188 ret = wmi_unified_ap_ps_cmd_send(wma->wmi_handle, peer_addr,
189 ¶m);
190 if (QDF_IS_STATUS_ERROR(ret)) {
191 wma_err("Failed to set WMI_AP_PS_PEER_PARAM_UAPSD for "QDF_MAC_ADDR_FMT,
192 QDF_MAC_ADDR_REF(peer_addr));
193 return ret;
194 }
195
196 wma_debug("Set WMI_AP_PS_PEER_PARAM_MAX_SP 0x%x for "QDF_MAC_ADDR_FMT,
197 max_sp_len, QDF_MAC_ADDR_REF(peer_addr));
198
199 param.vdev_id = vdev_id;
200 param.param = WMI_AP_PS_PEER_PARAM_MAX_SP;
201 param.value = max_sp_len;
202 ret = wmi_unified_ap_ps_cmd_send(wma->wmi_handle, peer_addr,
203 ¶m);
204 if (QDF_IS_STATUS_ERROR(ret)) {
205 wma_err("Failed to set WMI_AP_PS_PEER_PARAM_MAX_SP for "QDF_MAC_ADDR_FMT,
206 QDF_MAC_ADDR_REF(peer_addr));
207 return ret;
208 }
209
210 return QDF_STATUS_SUCCESS;
211 }
212
213 /**
214 * wma_update_edca_params_for_ac() - to update per ac EDCA parameters
215 * @edca_param: EDCA parameters
216 * @wmm_param: wmm parameters
217 * @ac: access category
218 *
219 * Return: none
220 */
wma_update_edca_params_for_ac(tSirMacEdcaParamRecord * edca_param,struct wmi_host_wme_vparams * wmm_param,int ac,bool mu_edca_param,uint8_t * debug_str,uint32_t debug_str_size,uint32_t * len)221 void wma_update_edca_params_for_ac(tSirMacEdcaParamRecord *edca_param,
222 struct wmi_host_wme_vparams *wmm_param,
223 int ac, bool mu_edca_param,
224 uint8_t *debug_str,
225 uint32_t debug_str_size, uint32_t *len)
226 {
227 wmm_param->cwmin = WMA_WMM_EXPO_TO_VAL(edca_param->cw.min);
228 wmm_param->cwmax = WMA_WMM_EXPO_TO_VAL(edca_param->cw.max);
229 wmm_param->aifs = edca_param->aci.aifsn;
230 if (mu_edca_param)
231 wmm_param->mu_edca_timer = edca_param->mu_edca_timer;
232 else
233 wmm_param->txoplimit = edca_param->txoplimit;
234 wmm_param->acm = edca_param->aci.acm;
235
236 wmm_param->noackpolicy = edca_param->no_ack;
237
238 *len += qdf_scnprintf(debug_str + *len, debug_str_size - *len,
239 "AC[%d]: AIFS %d Min %d Max %d %s %d ACM %d NOACK %d, ",
240 ac, wmm_param->aifs, wmm_param->cwmin,
241 wmm_param->cwmax,
242 mu_edca_param ? "MU_EDCA TIMER" : "TXOP",
243 mu_edca_param ? wmm_param->mu_edca_timer : wmm_param->txoplimit,
244 wmm_param->acm, wmm_param->noackpolicy);
245 }
246
247 /**
248 * wma_set_tx_power() - set tx power limit in fw
249 * @handle: wma handle
250 * @tx_pwr_params: tx power parameters
251 *
252 * Return: none
253 */
wma_set_tx_power(WMA_HANDLE handle,tMaxTxPowerParams * tx_pwr_params)254 void wma_set_tx_power(WMA_HANDLE handle,
255 tMaxTxPowerParams *tx_pwr_params)
256 {
257 tp_wma_handle wma_handle = (tp_wma_handle) handle;
258 uint8_t vdev_id;
259 QDF_STATUS ret = QDF_STATUS_E_FAILURE;
260 int8_t max_reg_power;
261 struct wma_txrx_node *iface;
262
263 if (tx_pwr_params->dev_mode == QDF_SAP_MODE ||
264 tx_pwr_params->dev_mode == QDF_P2P_GO_MODE) {
265 ret = wma_find_vdev_id_by_addr(wma_handle,
266 tx_pwr_params->bssId.bytes,
267 &vdev_id);
268 } else {
269 ret = wma_find_vdev_id_by_bssid(wma_handle,
270 tx_pwr_params->bssId.bytes,
271 &vdev_id);
272 }
273 if (ret) {
274 wma_err("vdev id is invalid for "QDF_MAC_ADDR_FMT,
275 QDF_MAC_ADDR_REF(tx_pwr_params->bssId.bytes));
276 qdf_mem_free(tx_pwr_params);
277 return;
278 }
279
280 if (!wma_is_vdev_up(vdev_id)) {
281 wma_err("vdev id %d is not up for "QDF_MAC_ADDR_FMT, vdev_id,
282 QDF_MAC_ADDR_REF(tx_pwr_params->bssId.bytes));
283 qdf_mem_free(tx_pwr_params);
284 return;
285 }
286
287 iface = &wma_handle->interfaces[vdev_id];
288 if (tx_pwr_params->power == 0) {
289 /* set to default. Since the app does not care the tx power
290 * we keep the previous setting
291 */
292 mlme_set_tx_power(iface->vdev, tx_pwr_params->power);
293 ret = 0;
294 goto end;
295 }
296
297 max_reg_power = mlme_get_max_reg_power(iface->vdev);
298
299 if (max_reg_power != 0) {
300 /* make sure tx_power less than max_tx_power */
301 if (tx_pwr_params->power > max_reg_power) {
302 tx_pwr_params->power = max_reg_power;
303 }
304 }
305 if (mlme_get_tx_power(iface->vdev) != tx_pwr_params->power) {
306
307 /* tx_power changed, Push the tx_power to FW */
308 wma_nofl_debug("TXP[W][set_tx_pwr]: %d", tx_pwr_params->power);
309 ret = wma_vdev_set_param(wma_handle->wmi_handle, vdev_id,
310 wmi_vdev_param_tx_pwrlimit,
311 tx_pwr_params->power);
312 if (ret == QDF_STATUS_SUCCESS)
313 mlme_set_tx_power(iface->vdev, tx_pwr_params->power);
314 } else {
315 /* no tx_power change */
316 ret = QDF_STATUS_SUCCESS;
317 }
318 end:
319 qdf_mem_free(tx_pwr_params);
320 if (QDF_IS_STATUS_ERROR(ret))
321 wma_err("Failed to set vdev param wmi_vdev_param_tx_pwrlimit");
322 }
323
324 /**
325 * wma_set_max_tx_power() - set max tx power limit in fw
326 * @handle: wma handle
327 * @tx_pwr_params: tx power parameters
328 *
329 * Return: none
330 */
wma_set_max_tx_power(WMA_HANDLE handle,tMaxTxPowerParams * tx_pwr_params)331 void wma_set_max_tx_power(WMA_HANDLE handle,
332 tMaxTxPowerParams *tx_pwr_params)
333 {
334 tp_wma_handle wma_handle = (tp_wma_handle) handle;
335 uint8_t vdev_id;
336 QDF_STATUS ret = QDF_STATUS_E_FAILURE;
337 int8_t max_reg_power;
338 struct wma_txrx_node *iface;
339 int8_t max_tx_power;
340 struct wlan_channel *channel;
341 uint16_t ch_freq;
342
343 if (tx_pwr_params->dev_mode == QDF_SAP_MODE ||
344 tx_pwr_params->dev_mode == QDF_P2P_GO_MODE) {
345 ret = wma_find_vdev_id_by_addr(wma_handle,
346 tx_pwr_params->bssId.bytes,
347 &vdev_id);
348 } else {
349 ret = wma_find_vdev_id_by_bssid(wma_handle,
350 tx_pwr_params->bssId.bytes,
351 &vdev_id);
352 }
353 if (ret) {
354 wma_err("vdev id is invalid for "QDF_MAC_ADDR_FMT,
355 QDF_MAC_ADDR_REF(tx_pwr_params->bssId.bytes));
356 qdf_mem_free(tx_pwr_params);
357 return;
358 }
359
360 if (!wma_is_vdev_up(vdev_id)) {
361 wma_err("vdev id %d is not up", vdev_id);
362 qdf_mem_free(tx_pwr_params);
363 return;
364 }
365
366 iface = &wma_handle->interfaces[vdev_id];
367 channel = wlan_vdev_get_active_channel(iface->vdev);
368 if (channel) {
369 ch_freq = channel->ch_freq;
370 } else {
371 wma_err("Failed to get active channel");
372 qdf_mem_free(tx_pwr_params);
373 return;
374 }
375 max_reg_power = wlan_reg_get_channel_reg_power_for_freq(
376 wma_handle->mac_context->pdev, ch_freq);
377 /*
378 * When user tx power as auto, host will configure
379 * the tx power as max regulatory power allowed for
380 * that channel which signifies that it will be the
381 * upper limit for tx power used while transmission
382 */
383 if (tx_pwr_params->power == 0)
384 max_tx_power = max_reg_power;
385 else
386 max_tx_power = QDF_MIN(tx_pwr_params->power, max_reg_power);
387
388 wma_nofl_debug("TXP[W][set_max_pwr_req]: %d", max_tx_power);
389 ret = wma_vdev_set_param(wma_handle->wmi_handle, vdev_id,
390 wmi_vdev_param_tx_pwrlimit,
391 max_tx_power);
392 if (ret == QDF_STATUS_SUCCESS)
393 mlme_set_tx_power(iface->vdev, max_tx_power);
394 qdf_mem_free(tx_pwr_params);
395 if (QDF_IS_STATUS_ERROR(ret))
396 wma_err("Failed to set vdev param wmi_vdev_param_tx_pwrlimit");
397 }
398
399 /**
400 * wmi_unified_set_sta_ps() - set sta powersave params in fw
401 * @handle: wma handle
402 * @vdev_id: vdev id
403 * @val: value
404 *
405 * Return: QDF_STATUS_SUCCESS for success or error code
406 */
wmi_unified_set_sta_ps(wmi_unified_t wmi_handle,uint32_t vdev_id,uint8_t val)407 static QDF_STATUS wmi_unified_set_sta_ps(wmi_unified_t wmi_handle,
408 uint32_t vdev_id, uint8_t val)
409 {
410 QDF_STATUS ret;
411
412 ret = wmi_unified_set_sta_ps_mode(wmi_handle, vdev_id,
413 val);
414 if (QDF_IS_STATUS_ERROR(ret))
415 wma_err("Failed to send set Mimo PS ret = %d", ret);
416
417 return QDF_STATUS_SUCCESS;
418 }
419
420 /**
421 * wma_get_uapsd_mask() - get uapsd mask based on uapsd parameters
422 * @uapsd_params: uapsed parameters
423 *
424 * Return: uapsd mask
425 */
wma_get_uapsd_mask(tpUapsd_Params uapsd_params)426 static inline uint32_t wma_get_uapsd_mask(tpUapsd_Params uapsd_params)
427 {
428 uint32_t uapsd_val = 0;
429
430 if (uapsd_params->beDeliveryEnabled)
431 uapsd_val |= WMI_STA_PS_UAPSD_AC0_DELIVERY_EN;
432
433 if (uapsd_params->beTriggerEnabled)
434 uapsd_val |= WMI_STA_PS_UAPSD_AC0_TRIGGER_EN;
435
436 if (uapsd_params->bkDeliveryEnabled)
437 uapsd_val |= WMI_STA_PS_UAPSD_AC1_DELIVERY_EN;
438
439 if (uapsd_params->bkTriggerEnabled)
440 uapsd_val |= WMI_STA_PS_UAPSD_AC1_TRIGGER_EN;
441
442 if (uapsd_params->viDeliveryEnabled)
443 uapsd_val |= WMI_STA_PS_UAPSD_AC2_DELIVERY_EN;
444
445 if (uapsd_params->viTriggerEnabled)
446 uapsd_val |= WMI_STA_PS_UAPSD_AC2_TRIGGER_EN;
447
448 if (uapsd_params->voDeliveryEnabled)
449 uapsd_val |= WMI_STA_PS_UAPSD_AC3_DELIVERY_EN;
450
451 if (uapsd_params->voTriggerEnabled)
452 uapsd_val |= WMI_STA_PS_UAPSD_AC3_TRIGGER_EN;
453
454 return uapsd_val;
455 }
456
457 /**
458 * wma_set_force_sleep() - set power save parameters to fw
459 * @wma: wma handle
460 * @vdev_id: vdev id
461 * @enable: enable/disable
462 * @ps_param: OPM params
463 * @enable_ps: enable power save
464 *
465 * Return: QDF_STATUS_SUCCESS for success or error code
466 */
wma_set_force_sleep(tp_wma_handle wma,uint32_t vdev_id,uint8_t enable,struct wma_ps_params * ps_params,bool enable_ps)467 static QDF_STATUS wma_set_force_sleep(tp_wma_handle wma,
468 uint32_t vdev_id,
469 uint8_t enable,
470 struct wma_ps_params *ps_params,
471 bool enable_ps)
472 {
473 QDF_STATUS ret;
474 /* get mac to access CFG data base */
475 struct mac_context *mac = cds_get_context(QDF_MODULE_ID_PE);
476 uint32_t rx_wake_policy;
477 uint32_t tx_wake_threshold;
478 uint32_t pspoll_count;
479 uint32_t psmode;
480 struct wlan_objmgr_vdev *vdev;
481 u32 listen_interval = 0;
482
483 wma_debug("Set Force Sleep vdevId %d val %d", vdev_id, enable);
484
485 if (!mac) {
486 wma_err("Unable to get PE context");
487 return QDF_STATUS_E_NOMEM;
488 }
489
490 if (enable) {
491 /* override normal configuration and force station asleep */
492 rx_wake_policy = WMI_STA_PS_RX_WAKE_POLICY_POLL_UAPSD;
493 tx_wake_threshold = WMI_STA_PS_TX_WAKE_THRESHOLD_NEVER;
494
495 if (ucfg_pmo_get_max_ps_poll(mac->psoc))
496 pspoll_count =
497 (uint32_t)ucfg_pmo_get_max_ps_poll(mac->psoc);
498 else
499 pspoll_count = WMA_DEFAULT_MAX_PSPOLL_BEFORE_WAKE;
500
501 psmode = WMI_STA_PS_MODE_ENABLED;
502 } else {
503 /* Ps Poll Wake Policy */
504 if (ucfg_pmo_get_max_ps_poll(mac->psoc)) {
505 /* Ps Poll is enabled */
506 rx_wake_policy = WMI_STA_PS_RX_WAKE_POLICY_POLL_UAPSD;
507 pspoll_count =
508 (uint32_t)ucfg_pmo_get_max_ps_poll(mac->psoc);
509 tx_wake_threshold = WMI_STA_PS_TX_WAKE_THRESHOLD_NEVER;
510 } else {
511 rx_wake_policy = WMI_STA_PS_RX_WAKE_POLICY_WAKE;
512 pspoll_count = WMI_STA_PS_PSPOLL_COUNT_NO_MAX;
513 tx_wake_threshold = WMI_STA_PS_TX_WAKE_THRESHOLD_ALWAYS;
514 }
515 psmode = WMI_STA_PS_MODE_ENABLED;
516 }
517
518 /*
519 * Advanced power save is enabled by default in Firmware
520 * So Disable advanced power save explicitly
521 */
522 ret = wma_unified_set_sta_ps_param(wma->wmi_handle, vdev_id,
523 WMI_STA_PS_ENABLE_OPM,
524 ps_params->opm_mode);
525 if (QDF_IS_STATUS_ERROR(ret)) {
526 wma_err("%s(%d) Power Failed vdevId %d",
527 ps_params->opm_mode ? "Enable" : "Disable",
528 ps_params->opm_mode, vdev_id);
529 return ret;
530 }
531 wma_debug("Power %s(%d) vdevId %d",
532 ps_params->opm_mode ? "Enabled" : "Disabled",
533 ps_params->opm_mode, vdev_id);
534
535 /* Set the Tx/Rx InActivity */
536 ret = wma_unified_set_sta_ps_param(wma->wmi_handle, vdev_id,
537 WMI_STA_PS_PARAM_INACTIVITY_TIME,
538 ps_params->ps_ito);
539
540 if (QDF_IS_STATUS_ERROR(ret)) {
541 wma_err("Setting Tx/Rx InActivity Failed vdevId %d InAct %d",
542 vdev_id, ps_params->ps_ito);
543 return ret;
544 }
545 wma_debug("Set Tx/Rx InActivity vdevId %d InAct %d",
546 vdev_id, ps_params->ps_ito);
547
548 ret = wma_unified_set_sta_ps_param(wma->wmi_handle, vdev_id,
549 WMI_STA_PS_PARAM_SPEC_WAKE_INTERVAL,
550 ps_params->spec_wake);
551
552 if (QDF_IS_STATUS_ERROR(ret)) {
553 wma_err("Setting Spec wake Failed vdevId %d InAct %d",
554 vdev_id, ps_params->spec_wake);
555 return ret;
556 }
557 wma_debug("Set Spec wake vdevId %d InAct %d",
558 vdev_id, ps_params->spec_wake);
559
560 /* Set the Wake Policy to WMI_STA_PS_RX_WAKE_POLICY_POLL_UAPSD */
561 ret = wma_unified_set_sta_ps_param(wma->wmi_handle, vdev_id,
562 WMI_STA_PS_PARAM_RX_WAKE_POLICY,
563 rx_wake_policy);
564
565 if (QDF_IS_STATUS_ERROR(ret)) {
566 wma_err("Setting wake policy Failed vdevId %d", vdev_id);
567 return ret;
568 }
569 wma_debug("Setting wake policy to %d vdevId %d",
570 rx_wake_policy, vdev_id);
571
572 /* Set the Tx Wake Threshold */
573 ret = wma_unified_set_sta_ps_param(wma->wmi_handle, vdev_id,
574 WMI_STA_PS_PARAM_TX_WAKE_THRESHOLD,
575 tx_wake_threshold);
576
577 if (QDF_IS_STATUS_ERROR(ret)) {
578 wma_err("Setting TxWake Threshold vdevId %d", vdev_id);
579 return ret;
580 }
581 wma_debug("Setting TxWake Threshold to %d vdevId %d",
582 tx_wake_threshold, vdev_id);
583
584 /* Set the Ps Poll Count */
585 ret = wma_unified_set_sta_ps_param(wma->wmi_handle, vdev_id,
586 WMI_STA_PS_PARAM_PSPOLL_COUNT,
587 pspoll_count);
588
589 if (QDF_IS_STATUS_ERROR(ret)) {
590 wma_err("Set Ps Poll Count Failed vdevId %d ps poll cnt %d",
591 vdev_id, pspoll_count);
592 return ret;
593 }
594 wma_debug("Set Ps Poll Count vdevId %d ps poll cnt %d",
595 vdev_id, pspoll_count);
596
597 /* Enable Sta Mode Power save */
598 if (enable_ps) {
599 ret = wmi_unified_set_sta_ps(wma->wmi_handle, vdev_id, true);
600
601 if (QDF_IS_STATUS_ERROR(ret)) {
602 wma_err("Enable Sta Mode Ps Failed vdevId %d",
603 vdev_id);
604 return ret;
605 }
606 }
607
608 /* Set Listen Interval */
609 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(mac->psoc, vdev_id,
610 WLAN_LEGACY_WMA_ID);
611 /* If user has configured listen interval already
612 * No need to send vdev set param cmd
613 */
614 if (vdev) {
615 ret = wlan_pmo_get_listen_interval(vdev, &listen_interval);
616 wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_WMA_ID);
617 }
618
619 if (!listen_interval || QDF_IS_STATUS_ERROR(ret)) {
620 listen_interval = mac->mlme_cfg->sap_cfg.listen_interval;
621 ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
622 wmi_vdev_param_listen_interval,
623 listen_interval);
624 }
625 if (QDF_IS_STATUS_ERROR(ret)) {
626 /* Even it fails continue Fw will take default LI */
627 wma_err("Failed to Set Listen Interval vdevId %d", vdev_id);
628 }
629 wma_debug("Set Listen Interval vdevId %d Listen Intv %d",
630 vdev_id, listen_interval);
631
632 return QDF_STATUS_SUCCESS;
633 }
634
wma_wlan_pmo_get_ps_params(struct wlan_objmgr_vdev * vdev,struct wma_ps_params * ps_params)635 static QDF_STATUS wma_wlan_pmo_get_ps_params(struct wlan_objmgr_vdev *vdev,
636 struct wma_ps_params *ps_params)
637 {
638 struct pmo_ps_params pmo_ps_param = {0};
639 QDF_STATUS status;
640
641 status = wlan_pmo_get_ps_params(vdev, &pmo_ps_param);
642 if (QDF_IS_STATUS_ERROR(status))
643 return status;
644
645 switch (pmo_ps_param.opm_mode) {
646 case PMO_PS_ADVANCED_POWER_SAVE_DISABLE:
647 ps_params->opm_mode = WMI_STA_PS_OPM_CONSERVATIVE;
648 break;
649 case PMO_PS_ADVANCED_POWER_SAVE_ENABLE:
650 ps_params->opm_mode = WMI_STA_PS_OPM_AGGRESSIVE;
651 break;
652 case PMO_PS_ADVANCED_POWER_SAVE_USER_DEFINED:
653 ps_params->opm_mode = WMI_STA_PS_USER_DEF;
654 break;
655 default:
656 wma_err("Invalid opm_mode:%d", pmo_ps_param.opm_mode);
657 return QDF_STATUS_E_INVAL;
658 }
659 ps_params->ps_ito = pmo_ps_param.ps_ito;
660 ps_params->spec_wake = pmo_ps_param.spec_wake;
661
662 return status;
663 }
664
wma_enable_sta_ps_mode(tpEnablePsParams ps_req)665 void wma_enable_sta_ps_mode(tpEnablePsParams ps_req)
666 {
667 uint32_t vdev_id = ps_req->sessionid;
668 QDF_STATUS ret;
669 struct wma_txrx_node *iface;
670 t_wma_handle *wma_handle;
671 struct wma_ps_params ps_params = {0};
672
673 wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
674 if (!wma_handle)
675 return;
676
677 iface = &wma_handle->interfaces[vdev_id];
678
679 if (!iface || !iface->vdev) {
680 wma_err("vdev is NULL for vdev_%d", vdev_id);
681 return;
682 }
683
684 ret = wma_wlan_pmo_get_ps_params(iface->vdev, &ps_params);
685 if (QDF_IS_STATUS_ERROR(ret))
686 return;
687
688 if (eSIR_ADDON_NOTHING == ps_req->psSetting) {
689 if (ps_params.opm_mode && iface->uapsd_cached_val) {
690 ps_params.opm_mode = WMI_STA_PS_OPM_CONSERVATIVE;
691 wma_debug("Advanced power save is disabled");
692 }
693 wma_debug("Enable Sta Mode Ps vdevId %d", vdev_id);
694 ret = wma_unified_set_sta_ps_param(wma_handle->wmi_handle,
695 vdev_id,
696 WMI_STA_PS_PARAM_UAPSD, 0);
697 if (QDF_IS_STATUS_ERROR(ret)) {
698 wma_err("Set Uapsd param 0 Failed vdevId %d", vdev_id);
699 return;
700 }
701
702 ret = wma_set_force_sleep(wma_handle, vdev_id, false,
703 &ps_params, true);
704 if (QDF_IS_STATUS_ERROR(ret)) {
705 wma_err("Enable Sta Ps Failed vdevId %d", vdev_id);
706 return;
707 }
708 } else if (eSIR_ADDON_ENABLE_UAPSD == ps_req->psSetting) {
709 uint32_t uapsd_val = 0;
710
711 uapsd_val = wma_get_uapsd_mask(&ps_req->uapsdParams);
712 if (uapsd_val != iface->uapsd_cached_val) {
713 wma_debug("Enable Uapsd vdevId %d Mask %d",
714 vdev_id, uapsd_val);
715 ret =
716 wma_unified_set_sta_ps_param(wma_handle->wmi_handle,
717 vdev_id,
718 WMI_STA_PS_PARAM_UAPSD,
719 uapsd_val);
720 if (QDF_IS_STATUS_ERROR(ret)) {
721 wma_err("Enable Uapsd Failed vdevId %d",
722 vdev_id);
723 return;
724 }
725 /* Cache the Uapsd Mask */
726 iface->uapsd_cached_val = uapsd_val;
727 } else {
728 wma_debug("Already Uapsd Enabled vdevId %d Mask %d",
729 vdev_id, uapsd_val);
730 }
731
732 if (!!ps_params.opm_mode && !!iface->uapsd_cached_val) {
733 ps_params.opm_mode = WMI_STA_PS_OPM_CONSERVATIVE;
734 wma_debug("Qpower is disabled");
735 }
736 wma_debug("Enable Forced Sleep vdevId %d", vdev_id);
737 ret = wma_set_force_sleep(wma_handle, vdev_id, true,
738 &ps_params, true);
739
740 if (QDF_IS_STATUS_ERROR(ret)) {
741 wma_err("Enable Forced Sleep Failed vdevId %d",
742 vdev_id);
743 return;
744 }
745 }
746
747 if (wma_handle->ito_repeat_count) {
748 wma_debug("Set ITO count to %d for vdevId %d",
749 wma_handle->ito_repeat_count, vdev_id);
750
751 ret = wma_unified_set_sta_ps_param(wma_handle->wmi_handle,
752 vdev_id,
753 WMI_STA_PS_PARAM_MAX_RESET_ITO_COUNT_ON_TIM_NO_TXRX,
754 wma_handle->ito_repeat_count);
755 if (QDF_IS_STATUS_ERROR(ret)) {
756 wma_err("Set ITO count failed vdevId %d Error %d",
757 vdev_id, ret);
758 return;
759 }
760 }
761
762 /* power save request succeeded */
763 iface->in_bmps = true;
764 }
765
766
767 /**
768 * wma_disable_sta_ps_mode() - disable sta powersave params in fw
769 * @wma: wma handle
770 * @ps_req: power save request
771 *
772 * Return: none
773 */
wma_disable_sta_ps_mode(tpDisablePsParams ps_req)774 void wma_disable_sta_ps_mode(tpDisablePsParams ps_req)
775 {
776 QDF_STATUS ret;
777 uint32_t vdev_id = ps_req->sessionid;
778 struct wma_txrx_node *iface;
779 t_wma_handle *wma_handle;
780
781 wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
782 if (!wma_handle)
783 return;
784
785 iface = &wma_handle->interfaces[vdev_id];
786
787 wma_debug("Disable Sta Mode Ps vdevId %d", vdev_id);
788
789 /* Disable Sta Mode Power save */
790 ret = wmi_unified_set_sta_ps(wma_handle->wmi_handle, vdev_id, false);
791 if (QDF_IS_STATUS_ERROR(ret)) {
792 wma_err("Disable Sta Mode Ps Failed vdevId %d", vdev_id);
793 return;
794 }
795 iface->in_bmps = false;
796
797 /* Disable UAPSD incase if additional Req came */
798 if (eSIR_ADDON_DISABLE_UAPSD == ps_req->psSetting) {
799 wma_debug("Disable Uapsd vdevId %d", vdev_id);
800 ret = wma_unified_set_sta_ps_param(wma_handle->wmi_handle,
801 vdev_id,
802 WMI_STA_PS_PARAM_UAPSD, 0);
803 if (QDF_IS_STATUS_ERROR(ret)) {
804 wma_err("Disable Uapsd Failed vdevId %d", vdev_id);
805 /*
806 * Even this fails we can proceed as success
807 * since we disabled powersave
808 */
809 }
810 }
811 }
812
813 /**
814 * wma_convert_opm_mode() - convert opm with equivalent wmi opm
815 * @opm_mode: Optimized power management mode
816 *
817 * Return: enum wmi_sta_ps_scheme_cfg
818 */
819 static enum wmi_sta_ps_scheme_cfg
wma_convert_opm_mode(enum wma_sta_ps_scheme_cfg opm_mode)820 wma_convert_opm_mode(enum wma_sta_ps_scheme_cfg opm_mode)
821 {
822 switch (opm_mode) {
823 case WMA_STA_PS_OPM_CONSERVATIVE:
824 return WMI_STA_PS_OPM_CONSERVATIVE;
825 case WMA_STA_PS_OPM_AGGRESSIVE:
826 return WMI_STA_PS_OPM_AGGRESSIVE;
827 case WMA_STA_PS_USER_DEF:
828 return WMI_STA_PS_USER_DEF;
829 default:
830 wma_err("Invalid opm_mode: %d", opm_mode);
831 return WMI_STA_PS_OPM_CONSERVATIVE;
832 }
833 }
834
wma_set_power_config(uint8_t vdev_id,enum wma_sta_ps_scheme_cfg power)835 QDF_STATUS wma_set_power_config(uint8_t vdev_id,
836 enum wma_sta_ps_scheme_cfg power)
837 {
838 tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
839
840 if (!wma)
841 return QDF_STATUS_E_INVAL;
842
843 wma_info("configuring power: %d", power);
844 return wma_unified_set_sta_ps_param(wma->wmi_handle,
845 vdev_id,
846 WMI_STA_PS_ENABLE_OPM,
847 wma_convert_opm_mode(power));
848 }
849
wma_set_power_config_ito(uint8_t vdev_id,uint16_t ps_ito)850 QDF_STATUS wma_set_power_config_ito(uint8_t vdev_id, uint16_t ps_ito)
851 {
852 tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
853
854 if (!wma) {
855 wma_err("wma_handle is NULL");
856 return QDF_STATUS_E_INVAL;
857 }
858
859 return wma_unified_set_sta_ps_param(wma->wmi_handle, vdev_id,
860 WMI_STA_PS_PARAM_INACTIVITY_TIME,
861 ps_ito);
862 }
863
wma_set_power_config_spec_wake(uint8_t vdev_id,uint16_t spec_wake)864 QDF_STATUS wma_set_power_config_spec_wake(uint8_t vdev_id, uint16_t spec_wake)
865 {
866 tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
867
868 if (!wma) {
869 wma_err("wma_handle is NULL");
870 return QDF_STATUS_E_INVAL;
871 }
872
873 return wma_unified_set_sta_ps_param(wma->wmi_handle, vdev_id,
874 WMI_STA_PS_PARAM_SPEC_WAKE_INTERVAL,
875 spec_wake);
876 }
877
wma_enable_uapsd_mode(tp_wma_handle wma,tpEnableUapsdParams ps_req)878 void wma_enable_uapsd_mode(tp_wma_handle wma, tpEnableUapsdParams ps_req)
879 {
880 QDF_STATUS ret;
881 uint32_t vdev_id = ps_req->sessionid;
882 uint32_t uapsd_val = 0;
883 struct wma_ps_params ps_params = {0};
884 struct wma_txrx_node *iface = &wma->interfaces[vdev_id];
885
886 if (!iface->vdev) {
887 wma_err("vdev is NULL for vdev_%d", vdev_id);
888 return;
889 }
890
891 ret = wma_wlan_pmo_get_ps_params(iface->vdev, &ps_params);
892 if (QDF_IS_STATUS_ERROR(ret)) {
893 wma_err("ps_param is invalid for vdev_%d", vdev_id);
894 return;
895 }
896
897 /* Disable Sta Mode Power save */
898 ret = wmi_unified_set_sta_ps(wma->wmi_handle, vdev_id, false);
899 if (QDF_IS_STATUS_ERROR(ret)) {
900 wma_err("Disable Sta Mode Ps Failed vdevId %d", vdev_id);
901 return;
902 }
903
904 uapsd_val = wma_get_uapsd_mask(&ps_req->uapsdParams);
905
906 wma_debug("Enable Uapsd vdevId %d Mask %d", vdev_id, uapsd_val);
907 ret = wma_unified_set_sta_ps_param(wma->wmi_handle, vdev_id,
908 WMI_STA_PS_PARAM_UAPSD, uapsd_val);
909 if (QDF_IS_STATUS_ERROR(ret)) {
910 wma_err("Enable Uapsd Failed vdevId %d", vdev_id);
911 return;
912 }
913
914 if (!!ps_params.opm_mode && !!uapsd_val) {
915 ps_params.opm_mode = 0;
916 wma_debug("Disable power %d", vdev_id);
917 }
918 iface->uapsd_cached_val = uapsd_val;
919 wma_debug("Enable Forced Sleep vdevId %d", vdev_id);
920 ret = wma_set_force_sleep(wma, vdev_id, true,
921 &ps_params, ps_req->uapsdParams.enable_ps);
922 if (QDF_IS_STATUS_ERROR(ret)) {
923 wma_err("Enable Forced Sleep Failed vdevId %d", vdev_id);
924 return;
925 }
926
927 }
928
929 /**
930 * wma_disable_uapsd_mode() - disable uapsd mode in fw
931 * @wma: wma handle
932 * @ps_req: power save request
933 *
934 * Return: none
935 */
wma_disable_uapsd_mode(tp_wma_handle wma,tpDisableUapsdParams ps_req)936 void wma_disable_uapsd_mode(tp_wma_handle wma,
937 tpDisableUapsdParams ps_req)
938 {
939 QDF_STATUS ret;
940 uint32_t vdev_id = ps_req->sessionid;
941 struct wma_ps_params ps_params = {0};
942 struct wma_txrx_node *iface = &wma->interfaces[vdev_id];
943
944 if (!iface->vdev) {
945 wma_err("vdev is null for vdev_%d", vdev_id);
946 return;
947 }
948
949 wma_debug("Disable Uapsd vdevId %d", vdev_id);
950
951 ret = wma_wlan_pmo_get_ps_params(iface->vdev, &ps_params);
952 if (QDF_IS_STATUS_ERROR(ret)) {
953 wma_err("ps_param is invalid for vdev_%d", vdev_id);
954 return;
955 }
956
957 /* Disable Sta Mode Power save */
958 ret = wmi_unified_set_sta_ps(wma->wmi_handle, vdev_id, false);
959 if (QDF_IS_STATUS_ERROR(ret)) {
960 wma_err("Disable Sta Mode Ps Failed vdevId %d", vdev_id);
961 return;
962 }
963
964 ret = wma_unified_set_sta_ps_param(wma->wmi_handle, vdev_id,
965 WMI_STA_PS_PARAM_UAPSD, 0);
966 if (QDF_IS_STATUS_ERROR(ret)) {
967 wma_err("Disable Uapsd Failed vdevId %d", vdev_id);
968 return;
969 }
970
971 /* Re enable Sta Mode Powersave with proper configuration */
972 ret = wma_set_force_sleep(wma, vdev_id, false,
973 &ps_params, true);
974 if (QDF_IS_STATUS_ERROR(ret)) {
975 wma_err("Disable Forced Sleep Failed vdevId %d", vdev_id);
976 return;
977 }
978 }
979
980 /**
981 * wma_set_sta_uapsd_auto_trig_cmd() - set uapsd auto trigger command
982 * @wmi_handle: wma handle
983 * @vdevid: vdev id
984 * @peer_addr: peer mac address
985 * @trig_param: auto trigger parameters
986 * @num_ac: number of access category
987 *
988 * This function sets the trigger
989 * uapsd params such as service interval, delay interval
990 * and suspend interval which will be used by the firmware
991 * to send trigger frames periodically when there is no
992 * traffic on the transmit side.
993 *
994 * Return: 0 for success or error code.
995 */
wma_set_sta_uapsd_auto_trig_cmd(wmi_unified_t wmi_handle,uint32_t vdevid,uint8_t peer_addr[QDF_MAC_ADDR_SIZE],struct sta_uapsd_params * trig_param,uint32_t num_ac)996 static QDF_STATUS wma_set_sta_uapsd_auto_trig_cmd(wmi_unified_t wmi_handle,
997 uint32_t vdevid,
998 uint8_t peer_addr[QDF_MAC_ADDR_SIZE],
999 struct sta_uapsd_params *trig_param,
1000 uint32_t num_ac)
1001 {
1002 QDF_STATUS ret;
1003 struct sta_uapsd_trig_params cmd = {0};
1004
1005 cmd.vdevid = vdevid;
1006 cmd.auto_triggerparam = trig_param;
1007 cmd.num_ac = num_ac;
1008
1009 qdf_mem_copy((uint8_t *) cmd.peer_addr, (uint8_t *) peer_addr,
1010 sizeof(uint8_t) * QDF_MAC_ADDR_SIZE);
1011 ret = wmi_unified_set_sta_uapsd_auto_trig_cmd(wmi_handle,
1012 &cmd);
1013 if (QDF_IS_STATUS_ERROR(ret))
1014 wma_err("Failed to send set uapsd param ret = %d", ret);
1015
1016 return ret;
1017 }
1018
wma_trigger_uapsd_params(tp_wma_handle wma_handle,uint32_t vdev_id,tp_wma_trigger_uapsd_params trigger_uapsd_params)1019 QDF_STATUS wma_trigger_uapsd_params(tp_wma_handle wma_handle, uint32_t vdev_id,
1020 tp_wma_trigger_uapsd_params
1021 trigger_uapsd_params)
1022 {
1023 QDF_STATUS ret;
1024 uint8_t *bssid;
1025 struct sta_uapsd_params uapsd_trigger_param;
1026
1027 wma_debug("Trigger uapsd params vdev id %d", vdev_id);
1028
1029 wma_debug("WMM AC %d User Priority %d SvcIntv %d DelIntv %d SusIntv %d",
1030 trigger_uapsd_params->wmm_ac,
1031 trigger_uapsd_params->user_priority,
1032 trigger_uapsd_params->service_interval,
1033 trigger_uapsd_params->delay_interval,
1034 trigger_uapsd_params->suspend_interval);
1035
1036 if (!wmi_service_enabled(wma_handle->wmi_handle,
1037 wmi_sta_uapsd_basic_auto_trig) ||
1038 !wmi_service_enabled(wma_handle->wmi_handle,
1039 wmi_sta_uapsd_var_auto_trig)) {
1040 wma_debug("Trigger uapsd is not supported vdev id %d", vdev_id);
1041 return QDF_STATUS_SUCCESS;
1042 }
1043
1044 uapsd_trigger_param.wmm_ac = trigger_uapsd_params->wmm_ac;
1045 uapsd_trigger_param.user_priority = trigger_uapsd_params->user_priority;
1046 uapsd_trigger_param.service_interval =
1047 trigger_uapsd_params->service_interval;
1048 uapsd_trigger_param.suspend_interval =
1049 trigger_uapsd_params->suspend_interval;
1050 uapsd_trigger_param.delay_interval =
1051 trigger_uapsd_params->delay_interval;
1052
1053 bssid = wma_get_vdev_bssid(wma_handle->interfaces[vdev_id].vdev);
1054 if (!bssid) {
1055 wma_err("Failed to get bssid for vdev_%d", vdev_id);
1056 return QDF_STATUS_E_FAILURE;
1057 }
1058 ret = wma_set_sta_uapsd_auto_trig_cmd(wma_handle->wmi_handle,
1059 vdev_id, bssid,
1060 &uapsd_trigger_param, 1);
1061 if (QDF_IS_STATUS_ERROR(ret)) {
1062 wma_err("Fail to send uapsd param cmd for vdevid %d ret = %d",
1063 ret, vdev_id);
1064 return ret;
1065 }
1066
1067 return ret;
1068 }
1069
wma_disable_uapsd_per_ac(tp_wma_handle wma_handle,uint32_t vdev_id,enum uapsd_ac ac)1070 QDF_STATUS wma_disable_uapsd_per_ac(tp_wma_handle wma_handle,
1071 uint32_t vdev_id, enum uapsd_ac ac)
1072 {
1073 QDF_STATUS ret;
1074 uint8_t *bssid;
1075 struct wma_txrx_node *iface = &wma_handle->interfaces[vdev_id];
1076 struct sta_uapsd_params uapsd_trigger_param;
1077 enum uapsd_up user_priority;
1078
1079 wma_debug("Disable Uapsd per ac vdevId %d ac %d", vdev_id, ac);
1080
1081 switch (ac) {
1082 case UAPSD_VO:
1083 iface->uapsd_cached_val &=
1084 ~(WMI_STA_PS_UAPSD_AC3_DELIVERY_EN |
1085 WMI_STA_PS_UAPSD_AC3_TRIGGER_EN);
1086 user_priority = UAPSD_UP_VO;
1087 break;
1088 case UAPSD_VI:
1089 iface->uapsd_cached_val &=
1090 ~(WMI_STA_PS_UAPSD_AC2_DELIVERY_EN |
1091 WMI_STA_PS_UAPSD_AC2_TRIGGER_EN);
1092 user_priority = UAPSD_UP_VI;
1093 break;
1094 case UAPSD_BK:
1095 iface->uapsd_cached_val &=
1096 ~(WMI_STA_PS_UAPSD_AC1_DELIVERY_EN |
1097 WMI_STA_PS_UAPSD_AC1_TRIGGER_EN);
1098 user_priority = UAPSD_UP_BK;
1099 break;
1100 case UAPSD_BE:
1101 iface->uapsd_cached_val &=
1102 ~(WMI_STA_PS_UAPSD_AC0_DELIVERY_EN |
1103 WMI_STA_PS_UAPSD_AC0_TRIGGER_EN);
1104 user_priority = UAPSD_UP_BE;
1105 break;
1106 default:
1107 wma_err("Invalid AC vdevId %d ac %d", vdev_id, ac);
1108 return QDF_STATUS_E_FAILURE;
1109 }
1110
1111 /*
1112 * Disable Auto Trigger Functionality before
1113 * disabling uapsd for a particular AC
1114 */
1115 uapsd_trigger_param.wmm_ac = ac;
1116 uapsd_trigger_param.user_priority = user_priority;
1117 uapsd_trigger_param.service_interval = 0;
1118 uapsd_trigger_param.suspend_interval = 0;
1119 uapsd_trigger_param.delay_interval = 0;
1120
1121 bssid = wma_get_vdev_bssid(wma_handle->interfaces[vdev_id].vdev);
1122 if (!bssid) {
1123 wma_err("Failed to get bssid for vdev_%d", vdev_id);
1124 return QDF_STATUS_E_FAILURE;
1125 }
1126 ret = wma_set_sta_uapsd_auto_trig_cmd(wma_handle->wmi_handle,
1127 vdev_id, bssid,
1128 &uapsd_trigger_param, 1);
1129 if (QDF_IS_STATUS_ERROR(ret)) {
1130 wma_err("Fail to send auto trig cmd for vdevid %d ret = %d",
1131 ret, vdev_id);
1132 return ret;
1133 }
1134
1135 ret = wma_unified_set_sta_ps_param(wma_handle->wmi_handle, vdev_id,
1136 WMI_STA_PS_PARAM_UAPSD,
1137 iface->uapsd_cached_val);
1138 if (QDF_IS_STATUS_ERROR(ret)) {
1139 wma_err("Disable Uapsd per ac Failed vdevId %d ac %d", vdev_id,
1140 ac);
1141 return ret;
1142 }
1143 wma_debug("Disable Uapsd per ac vdevId %d val %d", vdev_id,
1144 iface->uapsd_cached_val);
1145
1146 return QDF_STATUS_SUCCESS;
1147 }
1148
1149 /**
1150 * wma_get_temperature() - get pdev temperature req
1151 * @wmi_handle: wma handle
1152 *
1153 * Return: QDF_STATUS_SUCCESS for success or error code.
1154 */
wma_get_temperature(tp_wma_handle wma_handle)1155 QDF_STATUS wma_get_temperature(tp_wma_handle wma_handle)
1156 {
1157 QDF_STATUS ret = QDF_STATUS_SUCCESS;
1158
1159 ret = wmi_unified_get_temperature(wma_handle->wmi_handle);
1160 if (ret)
1161 wma_err("Failed to send set Mimo PS ret = %d", ret);
1162
1163 return ret;
1164 }
1165
1166 /**
1167 * wma_pdev_temperature_evt_handler() - pdev temperature event handler
1168 * @handle: wma handle
1169 * @event: event buffer
1170 * @len : length
1171 *
1172 * Return: 0 for success or error code.
1173 */
wma_pdev_temperature_evt_handler(void * handle,uint8_t * event,uint32_t len)1174 int wma_pdev_temperature_evt_handler(void *handle, uint8_t *event,
1175 uint32_t len)
1176 {
1177 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
1178 struct scheduler_msg sme_msg = { 0 };
1179 WMI_PDEV_TEMPERATURE_EVENTID_param_tlvs *param_buf;
1180 wmi_pdev_temperature_event_fixed_param *wmi_event;
1181
1182 param_buf = (WMI_PDEV_TEMPERATURE_EVENTID_param_tlvs *) event;
1183 if (!param_buf) {
1184 wma_err("Invalid pdev_temperature event buffer");
1185 return -EINVAL;
1186 }
1187
1188 wmi_event = param_buf->fixed_param;
1189 wma_info("temperature: %d", wmi_event->value);
1190
1191 sme_msg.type = eWNI_SME_MSG_GET_TEMPERATURE_IND;
1192 sme_msg.bodyptr = NULL;
1193 sme_msg.bodyval = wmi_event->value;
1194
1195 qdf_status = scheduler_post_message(QDF_MODULE_ID_WMA,
1196 QDF_MODULE_ID_SME,
1197 QDF_MODULE_ID_SME, &sme_msg);
1198 if (!QDF_IS_STATUS_SUCCESS(qdf_status))
1199 wma_err("Fail to post get temperature ind msg");
1200 return 0;
1201 }
1202
1203 #define MAX_PDEV_TXPOWER_PARAMS 2
1204 /* params being sent:
1205 * wmi_pdev_param_txpower_limit2g
1206 * wmi_pdev_param_txpower_limit5g
1207 */
1208
1209 /**
1210 * wma_process_tx_power_limits() - sends the power limits for 2g/5g to firmware
1211 * @handle: wma handle
1212 * @ptxlim: power limit value
1213 *
1214 * Return: QDF_STATUS_SUCCESS for success or error code.
1215 */
wma_process_tx_power_limits(WMA_HANDLE handle,struct tx_power_limit * ptxlim)1216 QDF_STATUS wma_process_tx_power_limits(WMA_HANDLE handle,
1217 struct tx_power_limit *ptxlim)
1218 {
1219 tp_wma_handle wma = (tp_wma_handle) handle;
1220 int32_t ret = 0;
1221 uint32_t txpower_params2g = 0;
1222 uint32_t txpower_params5g = 0;
1223 struct wmi_unified *wmi_handle;
1224 struct dev_set_param setparam[MAX_PDEV_TXPOWER_PARAMS] = {};
1225 uint8_t index = 0;
1226
1227 if (wma_validate_handle(wma))
1228 return QDF_STATUS_E_INVAL;
1229
1230 wmi_handle = wma->wmi_handle;
1231 if (wmi_validate_handle(wmi_handle))
1232 return QDF_STATUS_E_INVAL;
1233
1234 /* Set value and reason code for 2g and 5g power limit */
1235
1236 SET_PDEV_PARAM_TXPOWER_REASON(txpower_params2g,
1237 wmi_pdev_param_txpower_reason_sar);
1238 SET_PDEV_PARAM_TXPOWER_VALUE(txpower_params2g, ptxlim->txPower2g);
1239
1240 SET_PDEV_PARAM_TXPOWER_REASON(txpower_params5g,
1241 wmi_pdev_param_txpower_reason_sar);
1242 SET_PDEV_PARAM_TXPOWER_VALUE(txpower_params5g, ptxlim->txPower5g);
1243
1244 wma_debug("txpower2g: %x txpower5g: %x",
1245 txpower_params2g, txpower_params5g);
1246 ret = mlme_check_index_setparam(setparam,
1247 wmi_pdev_param_txpower_limit2g,
1248 txpower_params2g, index++,
1249 MAX_PDEV_TXPOWER_PARAMS);
1250 if (QDF_IS_STATUS_ERROR(ret)) {
1251 wma_err("failed at wmi_pdev_param_txpower_limit2g");
1252 goto error;
1253 }
1254 ret = mlme_check_index_setparam(setparam,
1255 wmi_pdev_param_txpower_limit5g,
1256 txpower_params5g, index++,
1257 MAX_PDEV_TXPOWER_PARAMS);
1258 if (QDF_IS_STATUS_ERROR(ret)) {
1259 wma_err("failed at wmi_pdev_param_txpower_limit5g");
1260 goto error;
1261 }
1262 ret = wma_send_multi_pdev_vdev_set_params(MLME_PDEV_SETPARAM,
1263 WMI_PDEV_ID_SOC, setparam,
1264 index);
1265 if (QDF_IS_STATUS_ERROR(ret))
1266 wma_err("failed to send tx power pdev set params");
1267 error:
1268 return ret;
1269 }
1270
1271 #ifdef WLAN_WMI_BCN
1272 /**
1273 * wma_add_p2p_ie() - add p2p IE
1274 * @frm: ptr where p2p ie needs to add
1275 *
1276 * Return: ptr after p2p ie
1277 */
wma_add_p2p_ie(uint8_t * frm)1278 static uint8_t *wma_add_p2p_ie(uint8_t *frm)
1279 {
1280 uint8_t wfa_oui[3] = WMA_P2P_WFA_OUI;
1281 struct p2p_ie *p2p_ie = (struct p2p_ie *)frm;
1282
1283 p2p_ie->p2p_id = WMA_P2P_IE_ID;
1284 p2p_ie->p2p_oui[0] = wfa_oui[0];
1285 p2p_ie->p2p_oui[1] = wfa_oui[1];
1286 p2p_ie->p2p_oui[2] = wfa_oui[2];
1287 p2p_ie->p2p_oui_type = WMA_P2P_WFA_VER;
1288 p2p_ie->p2p_len = 4;
1289 return frm + sizeof(struct p2p_ie);
1290 }
1291
1292 /**
1293 * wma_update_beacon_noa_ie() - update beacon ie
1294 * @bcn: beacon info
1295 * @new_noa_sub_ie_len: ie length
1296 *
1297 * Return: none
1298 */
wma_update_beacon_noa_ie(struct beacon_info * bcn,uint16_t new_noa_sub_ie_len)1299 static void wma_update_beacon_noa_ie(struct beacon_info *bcn,
1300 uint16_t new_noa_sub_ie_len)
1301 {
1302 struct p2p_ie *p2p_ie;
1303 uint8_t *buf;
1304
1305 /* if there is nothing to add, just return */
1306 if (new_noa_sub_ie_len == 0) {
1307 if (bcn->noa_sub_ie_len && bcn->noa_ie) {
1308 wma_debug("NoA is present in previous beacon, but not present in swba event, So Reset the NoA");
1309 /* TODO: Assuming p2p noa ie is last ie in the beacon */
1310 qdf_mem_zero(bcn->noa_ie, (bcn->noa_sub_ie_len +
1311 sizeof(struct p2p_ie)));
1312 bcn->len -= (bcn->noa_sub_ie_len +
1313 sizeof(struct p2p_ie));
1314 bcn->noa_ie = NULL;
1315 bcn->noa_sub_ie_len = 0;
1316 }
1317 wma_debug("No need to update NoA");
1318 return;
1319 }
1320
1321 if (bcn->noa_sub_ie_len && bcn->noa_ie) {
1322 /* NoA present in previous beacon, update it */
1323 wma_debug("NoA present in previous beacon, update the NoA IE, bcn->len %u bcn->noa_sub_ie_len %u",
1324 bcn->len, bcn->noa_sub_ie_len);
1325 bcn->len -= (bcn->noa_sub_ie_len + sizeof(struct p2p_ie));
1326 qdf_mem_zero(bcn->noa_ie,
1327 (bcn->noa_sub_ie_len + sizeof(struct p2p_ie)));
1328 } else { /* NoA is not present in previous beacon */
1329 wma_debug("NoA not present in previous beacon, add it bcn->len %u",
1330 bcn->len);
1331 buf = qdf_nbuf_data(bcn->buf);
1332 bcn->noa_ie = buf + bcn->len;
1333 }
1334
1335 if (bcn->len + sizeof(struct p2p_ie) + new_noa_sub_ie_len >
1336 SIR_MAX_BEACON_SIZE) {
1337 wma_err("exceed max beacon length, bcn->len %d, new_noa_sub_ie_len %d, p2p len %u",
1338 bcn->len, new_noa_sub_ie_len,
1339 (uint32_t)sizeof(struct p2p_ie));
1340 return;
1341 }
1342
1343 bcn->noa_sub_ie_len = new_noa_sub_ie_len;
1344 wma_add_p2p_ie(bcn->noa_ie);
1345 p2p_ie = (struct p2p_ie *)bcn->noa_ie;
1346 p2p_ie->p2p_len += new_noa_sub_ie_len;
1347 qdf_mem_copy((bcn->noa_ie + sizeof(struct p2p_ie)), bcn->noa_sub_ie,
1348 new_noa_sub_ie_len);
1349
1350 bcn->len += (new_noa_sub_ie_len + sizeof(struct p2p_ie));
1351 wma_debug("Updated beacon length with NoA Ie is %u", bcn->len);
1352 }
1353
1354 /**
1355 * wma_p2p_create_sub_ie_noa() - put p2p noa ie
1356 * @buf: buffer
1357 * @noa: noa element ie
1358 * @new_noa_sub_ie_len: ie length
1359 *
1360 * Return: none
1361 */
wma_p2p_create_sub_ie_noa(uint8_t * buf,struct p2p_sub_element_noa * noa,uint16_t * new_noa_sub_ie_len)1362 static void wma_p2p_create_sub_ie_noa(uint8_t *buf,
1363 struct p2p_sub_element_noa *noa,
1364 uint16_t *new_noa_sub_ie_len)
1365 {
1366 uint8_t tmp_octet = 0;
1367 int i;
1368 uint8_t *buf_start = buf;
1369
1370 *buf++ = WMA_P2P_SUB_ELEMENT_NOA; /* sub-element id */
1371 ASSERT(noa->num_descriptors <= WMA_MAX_NOA_DESCRIPTORS);
1372
1373 /*
1374 * Length = (2 octets for Index and CTWin/Opp PS) and
1375 * (13 octets for each NOA Descriptors)
1376 */
1377 P2PIE_PUT_LE16(buf, WMA_NOA_IE_SIZE(noa->num_descriptors));
1378 buf += 2;
1379
1380 *buf++ = noa->index; /* Instance Index */
1381
1382 tmp_octet = noa->ctwindow & WMA_P2P_NOA_IE_CTWIN_MASK;
1383 if (noa->oppPS)
1384 tmp_octet |= WMA_P2P_NOA_IE_OPP_PS_SET;
1385 *buf++ = tmp_octet; /* Opp Ps and CTWin capabilities */
1386
1387 for (i = 0; i < noa->num_descriptors; i++) {
1388 ASSERT(noa->noa_descriptors[i].type_count != 0);
1389
1390 *buf++ = noa->noa_descriptors[i].type_count;
1391
1392 P2PIE_PUT_LE32(buf, noa->noa_descriptors[i].duration);
1393 buf += 4;
1394 P2PIE_PUT_LE32(buf, noa->noa_descriptors[i].interval);
1395 buf += 4;
1396 P2PIE_PUT_LE32(buf, noa->noa_descriptors[i].start_time);
1397 buf += 4;
1398 }
1399 *new_noa_sub_ie_len = (buf - buf_start);
1400 }
1401
1402 /**
1403 * wma_update_noa() - update noa params
1404 * @beacon: beacon info
1405 * @noa_ie: noa ie
1406 *
1407 * Return: none
1408 */
wma_update_noa(struct beacon_info * beacon,struct p2p_sub_element_noa * noa_ie)1409 void wma_update_noa(struct beacon_info *beacon,
1410 struct p2p_sub_element_noa *noa_ie)
1411 {
1412 uint16_t new_noa_sub_ie_len;
1413
1414 /* Call this function by holding the spinlock on beacon->lock */
1415
1416 if (noa_ie) {
1417 if ((noa_ie->ctwindow == 0) && (noa_ie->oppPS == 0) &&
1418 (noa_ie->num_descriptors == 0)) {
1419 /* NoA is not present */
1420 wma_debug("NoA is not present");
1421 new_noa_sub_ie_len = 0;
1422 } else {
1423 /* Create the binary blob containing NOA sub-IE */
1424 wma_debug("Create NOA sub ie");
1425 wma_p2p_create_sub_ie_noa(&beacon->noa_sub_ie[0],
1426 noa_ie, &new_noa_sub_ie_len);
1427 }
1428 } else {
1429 wma_debug("No need to add NOA");
1430 new_noa_sub_ie_len = 0; /* no NOA IE sub-attributes */
1431 }
1432
1433 wma_update_beacon_noa_ie(beacon, new_noa_sub_ie_len);
1434 }
1435
1436 /**
1437 * wma_update_probe_resp_noa() - update noa IE in probe response
1438 * @wma_handle: wma handle
1439 * @noa_ie: noa ie
1440 *
1441 * Return: none
1442 */
wma_update_probe_resp_noa(tp_wma_handle wma_handle,struct p2p_sub_element_noa * noa_ie)1443 void wma_update_probe_resp_noa(tp_wma_handle wma_handle,
1444 struct p2p_sub_element_noa *noa_ie)
1445 {
1446 tSirP2PNoaAttr *noa_attr = qdf_mem_malloc(sizeof(tSirP2PNoaAttr));
1447 wma_debug("Received update NoA event");
1448 if (!noa_attr)
1449 return;
1450
1451 qdf_mem_zero(noa_attr, sizeof(tSirP2PNoaAttr));
1452
1453 noa_attr->index = noa_ie->index;
1454 noa_attr->oppPsFlag = noa_ie->oppPS;
1455 noa_attr->ctWin = noa_ie->ctwindow;
1456 if (!noa_ie->num_descriptors) {
1457 wma_debug("Zero NoA descriptors");
1458 } else {
1459 wma_debug("%d NoA descriptors", noa_ie->num_descriptors);
1460 noa_attr->uNoa1IntervalCnt =
1461 noa_ie->noa_descriptors[0].type_count;
1462 noa_attr->uNoa1Duration = noa_ie->noa_descriptors[0].duration;
1463 noa_attr->uNoa1Interval = noa_ie->noa_descriptors[0].interval;
1464 noa_attr->uNoa1StartTime =
1465 noa_ie->noa_descriptors[0].start_time;
1466 if (noa_ie->num_descriptors > 1) {
1467 noa_attr->uNoa2IntervalCnt =
1468 noa_ie->noa_descriptors[1].type_count;
1469 noa_attr->uNoa2Duration =
1470 noa_ie->noa_descriptors[1].duration;
1471 noa_attr->uNoa2Interval =
1472 noa_ie->noa_descriptors[1].interval;
1473 noa_attr->uNoa2StartTime =
1474 noa_ie->noa_descriptors[1].start_time;
1475 }
1476 }
1477 wma_debug("Sending SIR_HAL_P2P_NOA_ATTR_IND to LIM");
1478 wma_send_msg(wma_handle, SIR_HAL_P2P_NOA_ATTR_IND, (void *)noa_attr, 0);
1479 }
1480
1481 #else
wma_add_p2p_ie(uint8_t * frm)1482 static inline uint8_t *wma_add_p2p_ie(uint8_t *frm)
1483 {
1484 return 0;
1485 }
1486
1487 static inline void
wma_update_beacon_noa_ie(struct beacon_info * bcn,uint16_t new_noa_sub_ie_len)1488 wma_update_beacon_noa_ie(struct beacon_info *bcn,
1489 uint16_t new_noa_sub_ie_len)
1490 {
1491 }
1492
1493 static inline void
wma_p2p_create_sub_ie_noa(uint8_t * buf,struct p2p_sub_element_noa * noa,uint16_t * new_noa_sub_ie_len)1494 wma_p2p_create_sub_ie_noa(uint8_t *buf,
1495 struct p2p_sub_element_noa *noa,
1496 uint16_t *new_noa_sub_ie_len)
1497 {
1498 }
1499
wma_update_noa(struct beacon_info * beacon,struct p2p_sub_element_noa * noa_ie)1500 void wma_update_noa(struct beacon_info *beacon,
1501 struct p2p_sub_element_noa *noa_ie)
1502 {
1503 }
1504
wma_update_probe_resp_noa(tp_wma_handle wma_handle,struct p2p_sub_element_noa * noa_ie)1505 void wma_update_probe_resp_noa(tp_wma_handle wma_handle,
1506 struct p2p_sub_element_noa *noa_ie)
1507 {
1508 }
1509
1510 #endif
1511
1512 /**
1513 * wma_process_set_mimops_req() - Set the received MiMo PS state to firmware
1514 * @handle: wma handle
1515 * @mimops: MIMO powersave params
1516 *
1517 * Return: none
1518 */
wma_process_set_mimops_req(tp_wma_handle wma_handle,tSetMIMOPS * mimops)1519 void wma_process_set_mimops_req(tp_wma_handle wma_handle,
1520 tSetMIMOPS *mimops)
1521 {
1522 /* Translate to what firmware understands */
1523 if (mimops->htMIMOPSState == eSIR_HT_MIMO_PS_DYNAMIC)
1524 mimops->htMIMOPSState = WMI_PEER_MIMO_PS_DYNAMIC;
1525 else if (mimops->htMIMOPSState == eSIR_HT_MIMO_PS_STATIC)
1526 mimops->htMIMOPSState = WMI_PEER_MIMO_PS_STATIC;
1527 else if (mimops->htMIMOPSState == eSIR_HT_MIMO_PS_NO_LIMIT)
1528 mimops->htMIMOPSState = WMI_PEER_MIMO_PS_NONE;
1529
1530 wma_debug("htMIMOPSState = %d, sessionId = %d peerMac <"QDF_MAC_ADDR_FMT">",
1531 mimops->htMIMOPSState, mimops->sessionId,
1532 QDF_MAC_ADDR_REF(mimops->peerMac));
1533
1534 wma_set_peer_param(wma_handle, mimops->peerMac,
1535 WMI_HOST_PEER_MIMO_PS_STATE, mimops->htMIMOPSState,
1536 mimops->sessionId);
1537 }
1538
1539 /**
1540 * wma_set_mimops() - set MIMO powersave
1541 * @handle: wma handle
1542 * @vdev_id: vdev id
1543 * @value: value
1544 *
1545 * Return: QDF_STATUS_SUCCESS for success or error code.
1546 */
wma_set_mimops(tp_wma_handle wma,uint8_t vdev_id,int value)1547 QDF_STATUS wma_set_mimops(tp_wma_handle wma, uint8_t vdev_id, int value)
1548 {
1549 QDF_STATUS ret;
1550
1551 ret = wmi_unified_set_mimops(wma->wmi_handle, vdev_id,
1552 value);
1553 if (QDF_IS_STATUS_ERROR(ret))
1554 wma_err("Failed to send set Mimo PS ret = %d", ret);
1555
1556 return ret;
1557 }
1558
1559 /**
1560 * wma_notify_modem_power_state() - notify modem power state
1561 * @wma_ptr: wma handle
1562 * @pReq: modem power state
1563 *
1564 * Return: QDF_STATUS_SUCCESS for success or error code.
1565 */
wma_notify_modem_power_state(void * wma_ptr,tSirModemPowerStateInd * pReq)1566 QDF_STATUS wma_notify_modem_power_state(void *wma_ptr,
1567 tSirModemPowerStateInd *pReq)
1568 {
1569 QDF_STATUS status;
1570 tp_wma_handle wma = (tp_wma_handle) wma_ptr;
1571
1572 wma_debug("WMA notify Modem Power State %d", pReq->param);
1573
1574 status = wma_unified_modem_power_state(wma->wmi_handle, pReq->param);
1575 if (QDF_IS_STATUS_ERROR(status)) {
1576 wma_err("Failed to notify Modem Power State %d", pReq->param);
1577 return status;
1578 }
1579
1580 wma_debug("Successfully notify Modem Power State %d", pReq->param);
1581
1582 return QDF_STATUS_SUCCESS;
1583 }
1584
1585 /**
1586 * wma_set_idle_ps_config() - enable/disable Low Power Support(Pdev Specific)
1587 * @wma_ptr: wma handle
1588 * @idle_ps: idle powersave
1589 *
1590 * Return: QDF_STATUS_SUCCESS for success or error code.
1591 */
wma_set_idle_ps_config(void * wma_ptr,uint32_t idle_ps)1592 QDF_STATUS wma_set_idle_ps_config(void *wma_ptr, uint32_t idle_ps)
1593 {
1594 int32_t ret;
1595 tp_wma_handle wma = (tp_wma_handle) wma_ptr;
1596 struct pdev_params pdevparam = {};
1597
1598 wma_debug("WMA Set Idle Ps Config [1:set 0:clear] val %d", idle_ps);
1599
1600 /* Set Idle Mode Power Save Config */
1601 pdevparam.param_id = wmi_pdev_param_idle_ps_config;
1602 pdevparam.param_value = idle_ps;
1603 ret = wmi_unified_pdev_param_send(wma->wmi_handle,
1604 &pdevparam,
1605 WMA_WILDCARD_PDEV_ID);
1606
1607 if (ret) {
1608 wma_err("Fail to Set Idle Ps Config %d", idle_ps);
1609 return QDF_STATUS_E_FAILURE;
1610 }
1611 wma->in_imps = !!idle_ps;
1612
1613 wma_debug("Successfully Set Idle Ps Config %d", idle_ps);
1614 return QDF_STATUS_SUCCESS;
1615 }
1616
1617 /**
1618 * wma_set_smps_params() - set smps params
1619 * @wma: wma handle
1620 * @vdev_id: vdev id
1621 * @value: value
1622 *
1623 * Return: QDF_STATUS_SUCCESS for success or error code.
1624 */
wma_set_smps_params(tp_wma_handle wma,uint8_t vdev_id,int value)1625 QDF_STATUS wma_set_smps_params(tp_wma_handle wma, uint8_t vdev_id,
1626 int value)
1627 {
1628 QDF_STATUS ret;
1629
1630 if (!wma_is_vdev_valid(vdev_id)) {
1631 wma_err("Invalid VDEV ID: %d", vdev_id);
1632 return QDF_STATUS_E_INVAL;
1633 }
1634
1635 ret = wmi_unified_set_smps_params(wma->wmi_handle, vdev_id,
1636 value);
1637 if (QDF_IS_STATUS_ERROR(ret))
1638 wma_err("Failed to send set Mimo PS ret = %d", ret);
1639
1640 return ret;
1641 }
1642
1643 #ifdef FEATURE_TX_POWER
1644 /**
1645 * wma_set_tx_power_scale() - set tx power scale
1646 * @vdev_id: vdev id
1647 * @value: value
1648 *
1649 * Return: QDF_STATUS_SUCCESS for success or error code.
1650 */
wma_set_tx_power_scale(uint8_t vdev_id,int value)1651 QDF_STATUS wma_set_tx_power_scale(uint8_t vdev_id, int value)
1652 {
1653 QDF_STATUS ret;
1654 tp_wma_handle wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
1655
1656 if (!wma_handle)
1657 return QDF_STATUS_E_FAILURE;
1658
1659 if (!wma_is_vdev_up(vdev_id)) {
1660 wma_err("vdev id %d is not up", vdev_id);
1661 return QDF_STATUS_E_FAILURE;
1662 }
1663
1664 ret = wma_vdev_set_param(wma_handle->wmi_handle, vdev_id,
1665 wmi_vdev_param_txpower_scale, value);
1666 if (QDF_IS_STATUS_ERROR(ret))
1667 wma_err("Set tx power scale failed");
1668
1669 return ret;
1670 }
1671
1672 /**
1673 * wma_set_tx_power_scale_decr_db() - decrease power by DB value
1674 * @vdev_id: vdev id
1675 * @value: value
1676 *
1677 * Return: QDF_STATUS_SUCCESS for success or error code.
1678 */
wma_set_tx_power_scale_decr_db(uint8_t vdev_id,int value)1679 QDF_STATUS wma_set_tx_power_scale_decr_db(uint8_t vdev_id, int value)
1680 {
1681 QDF_STATUS ret;
1682 tp_wma_handle wma_handle = cds_get_context(QDF_MODULE_ID_WMA);
1683
1684 if (!wma_handle)
1685 return QDF_STATUS_E_FAILURE;
1686
1687 if (!wma_is_vdev_up(vdev_id)) {
1688 wma_err("vdev id %d is not up", vdev_id);
1689 return QDF_STATUS_E_FAILURE;
1690 }
1691
1692 ret = wma_vdev_set_param(wma_handle->wmi_handle, vdev_id,
1693 wmi_vdev_param_txpower_scale_decr_db, value);
1694 if (QDF_IS_STATUS_ERROR(ret))
1695 wma_err("Decrease tx power value failed");
1696
1697 return ret;
1698 }
1699
1700 /**
1701 * wma_enable_disable_imps() - enable/disable FW IMPS feature
1702 * @pdev_id: pdev id
1703 * @param_val: value
1704 *
1705 * Return: QDF_STATUS_SUCCESS for success or error code.
1706 */
wma_enable_disable_imps(uint32_t pdev_id,uint32_t param_val)1707 QDF_STATUS wma_enable_disable_imps(uint32_t pdev_id, uint32_t param_val)
1708 {
1709 tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA);
1710 struct pdev_params pparam = {0};
1711 QDF_STATUS status;
1712
1713 if (!wma)
1714 return QDF_STATUS_E_FAILURE;
1715
1716 pparam.is_host_pdev_id = false;
1717
1718 /* Enable-disable IMPS */
1719 pparam.param_id = WMI_PDEV_PARAM_IDLE_PS_CONFIG;
1720 pparam.param_value = param_val;
1721 status = wmi_unified_pdev_param_send(wma->wmi_handle,
1722 &pparam, pdev_id);
1723 if (QDF_IS_STATUS_ERROR(status))
1724 wma_err("Unable to enable/disable:(%d) IMPS",
1725 param_val);
1726
1727 wma->in_imps = !!param_val;
1728
1729 return status;
1730 }
1731 #endif /* FEATURE_TX_POWER */
1732
1733