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