blob: e383e3906d8f42b344046216d71b5da858a71161 [file] [log] [blame]
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001/*
Amar Singhala297bfa2015-10-15 15:07:29 -07002 * Copyright (c) 2013-2016 The Linux Foundation. All rights reserved.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21
22/*
23 * This file was originally distributed by Qualcomm Atheros, Inc.
24 * under proprietary terms before Copyright ownership was assigned
25 * to the Linux Foundation.
26 */
27
28/**
29 * DOC: wma_power.c
30 * This file contains powersave related functions.
31 */
32
33/* Header files */
34
35#include "wma.h"
36#include "wma_api.h"
37#include "cds_api.h"
38#include "wmi_unified_api.h"
39#include "wlan_qct_sys.h"
40#include "wni_api.h"
41#include "ani_global.h"
42#include "wmi_unified.h"
43#include "wni_cfg.h"
44#include "cfg_api.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080045#include "wlan_tgt_def_config.h"
46
Nirav Shahcbc6d722016-03-01 16:24:53 +053047#include "qdf_nbuf.h"
Anurag Chouhan6d760662016-02-20 16:05:43 +053048#include "qdf_types.h"
Anurag Chouhan600c3a02016-03-01 10:33:54 +053049#include "qdf_mem.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080050#include "ol_txrx_peer_find.h"
51
52#include "wma_types.h"
53#include "lim_api.h"
54#include "lim_session_utils.h"
55
56#include "cds_utils.h"
57
58#if !defined(REMOVE_PKT_LOG)
59#include "pktlog_ac.h"
60#endif /* REMOVE_PKT_LOG */
61
62#include "dbglog_host.h"
63#include "csr_api.h"
64#include "ol_fw.h"
65
66#include "dfs.h"
67#include "wma_internal.h"
68
69/**
Govind Singhd76a5b02016-03-08 15:12:14 +053070 * wma_unified_modem_power_state() - set modem power state to fw
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080071 * @wmi_handle: wmi handle
72 * @param_value: parameter value
73 *
74 * Return: 0 for success or error code
75 */
76static int
Govind Singhd76a5b02016-03-08 15:12:14 +053077wma_unified_modem_power_state(wmi_unified_t wmi_handle, uint32_t param_value)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080078{
79 int ret;
80 wmi_modem_power_state_cmd_param *cmd;
81 wmi_buf_t buf;
82 uint16_t len = sizeof(*cmd);
83
84 buf = wmi_buf_alloc(wmi_handle, len);
85 if (!buf) {
86 WMA_LOGE("%s:wmi_buf_alloc failed", __func__);
87 return -ENOMEM;
88 }
89 cmd = (wmi_modem_power_state_cmd_param *) wmi_buf_data(buf);
90 WMITLV_SET_HDR(&cmd->tlv_header,
91 WMITLV_TAG_STRUC_wmi_modem_power_state_cmd_param,
92 WMITLV_GET_STRUCT_TLVLEN
93 (wmi_modem_power_state_cmd_param));
94 cmd->modem_power_state = param_value;
95 WMA_LOGD("%s: Setting cmd->modem_power_state = %u", __func__,
96 param_value);
97 ret = wmi_unified_cmd_send(wmi_handle, buf, len,
98 WMI_MODEM_POWER_STATE_CMDID);
99 if (ret != EOK) {
100 WMA_LOGE("Failed to send notify cmd ret = %d", ret);
101 wmi_buf_free(buf);
102 }
103 return ret;
104}
105
106/**
Govind Singhd76a5b02016-03-08 15:12:14 +0530107 * wma_unified_set_sta_ps_param() - set sta power save parameter to fw
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800108 * @wmi_handle: wmi handle
109 * @vdev_id: vdev id
110 * @param: param
111 * @value: parameter value
112 *
Govind Singhd76a5b02016-03-08 15:12:14 +0530113 * Return: QDF_STATUS_SUCCESS for success or error code
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800114 */
Govind Singhd76a5b02016-03-08 15:12:14 +0530115QDF_STATUS wma_unified_set_sta_ps_param(wmi_unified_t wmi_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800116 uint32_t vdev_id, uint32_t param,
117 uint32_t value)
118{
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800119 tp_wma_handle wma;
120 struct wma_txrx_node *iface;
Govind Singhd76a5b02016-03-08 15:12:14 +0530121 struct sta_ps_params sta_ps_param = {0};
122 QDF_STATUS status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800123
Anurag Chouhan6d760662016-02-20 16:05:43 +0530124 wma = cds_get_context(QDF_MODULE_ID_WMA);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800125 if (NULL == wma) {
126 WMA_LOGE("%s: wma is NULL", __func__);
Govind Singhd76a5b02016-03-08 15:12:14 +0530127 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800128 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800129 WMA_LOGD("Set Sta Ps param vdevId %d Param %d val %d",
130 vdev_id, param, value);
Govind Singhd76a5b02016-03-08 15:12:14 +0530131 iface = &wma->interfaces[vdev_id];
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800132
Govind Singhd76a5b02016-03-08 15:12:14 +0530133 sta_ps_param.vdev_id = vdev_id;
134 sta_ps_param.param = param;
135 sta_ps_param.value = value;
136 status = wmi_unified_sta_ps_cmd_send(wmi_handle, &sta_ps_param);
137 if (QDF_IS_STATUS_ERROR(status))
138 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800139 /* Store the PS Status */
140 iface->ps_enabled = value ? true : false;
Govind Singhd76a5b02016-03-08 15:12:14 +0530141
142 return status;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800143}
144
145#ifdef QCA_IBSS_SUPPORT
146/**
147 * wma_set_ibss_pwrsave_params() - set ibss power save parameter to fw
148 * @wma: wma handle
149 * @vdev_id: vdev id
150 *
151 * Return: 0 for success or error code.
152 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530153QDF_STATUS
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800154wma_set_ibss_pwrsave_params(tp_wma_handle wma, uint8_t vdev_id)
155{
Govind Singhd76a5b02016-03-08 15:12:14 +0530156 QDF_STATUS ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800157
Govind Singhd76a5b02016-03-08 15:12:14 +0530158 ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800159 WMI_VDEV_PARAM_ATIM_WINDOW_LENGTH,
160 wma->wma_ibss_power_save_params.atimWindowLength);
Govind Singhd76a5b02016-03-08 15:12:14 +0530161 if (QDF_IS_STATUS_ERROR(ret)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800162 WMA_LOGE("Failed to set WMI_VDEV_PARAM_ATIM_WINDOW_LENGTH ret = %d",
163 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530164 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800165 }
166
Govind Singhd76a5b02016-03-08 15:12:14 +0530167 ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800168 WMI_VDEV_PARAM_IS_IBSS_POWER_SAVE_ALLOWED,
169 wma->wma_ibss_power_save_params.isPowerSaveAllowed);
Govind Singhd76a5b02016-03-08 15:12:14 +0530170 if (QDF_IS_STATUS_ERROR(ret)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800171 WMA_LOGE("Failed, set WMI_VDEV_PARAM_IS_IBSS_POWER_SAVE_ALLOWED ret=%d",
172 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530173 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800174 }
175
Govind Singhd76a5b02016-03-08 15:12:14 +0530176 ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800177 WMI_VDEV_PARAM_IS_POWER_COLLAPSE_ALLOWED,
178 wma->wma_ibss_power_save_params.isPowerCollapseAllowed);
Govind Singhd76a5b02016-03-08 15:12:14 +0530179 if (QDF_IS_STATUS_ERROR(ret)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800180 WMA_LOGE("Failed, set WMI_VDEV_PARAM_IS_POWER_COLLAPSE_ALLOWED ret=%d",
181 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530182 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800183 }
184
Govind Singhd76a5b02016-03-08 15:12:14 +0530185 ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800186 WMI_VDEV_PARAM_IS_AWAKE_ON_TXRX_ENABLED,
187 wma->wma_ibss_power_save_params.isAwakeonTxRxEnabled);
Govind Singhd76a5b02016-03-08 15:12:14 +0530188 if (QDF_IS_STATUS_ERROR(ret)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800189 WMA_LOGE("Failed, set WMI_VDEV_PARAM_IS_AWAKE_ON_TXRX_ENABLED ret=%d",
190 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530191 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800192 }
193
Govind Singhd76a5b02016-03-08 15:12:14 +0530194 ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800195 WMI_VDEV_PARAM_INACTIVITY_CNT,
196 wma->wma_ibss_power_save_params.inactivityCount);
Govind Singhd76a5b02016-03-08 15:12:14 +0530197 if (QDF_IS_STATUS_ERROR(ret)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800198 WMA_LOGE("Failed, set WMI_VDEV_PARAM_INACTIVITY_CNT ret=%d",
199 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530200 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800201 }
202
Govind Singhd76a5b02016-03-08 15:12:14 +0530203 ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800204 WMI_VDEV_PARAM_TXSP_END_INACTIVITY_TIME_MS,
205 wma->wma_ibss_power_save_params.txSPEndInactivityTime);
Govind Singhd76a5b02016-03-08 15:12:14 +0530206 if (QDF_IS_STATUS_ERROR(ret)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800207 WMA_LOGE("Failed, set WMI_VDEV_PARAM_TXSP_END_INACTIVITY_TIME_MS ret=%d",
208 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530209 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800210 }
211
Govind Singhd76a5b02016-03-08 15:12:14 +0530212 ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800213 WMI_VDEV_PARAM_IBSS_PS_WARMUP_TIME_SECS,
214 wma->wma_ibss_power_save_params.ibssPsWarmupTime);
Govind Singhd76a5b02016-03-08 15:12:14 +0530215 if (QDF_IS_STATUS_ERROR(ret)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800216 WMA_LOGE("Failed, set WMI_VDEV_PARAM_IBSS_PS_WARMUP_TIME_SECS ret=%d",
217 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530218 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800219 }
220
Govind Singhd76a5b02016-03-08 15:12:14 +0530221 ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800222 WMI_VDEV_PARAM_IBSS_PS_1RX_CHAIN_IN_ATIM_WINDOW_ENABLE,
223 wma->wma_ibss_power_save_params.ibssPs1RxChainInAtimEnable);
Govind Singhd76a5b02016-03-08 15:12:14 +0530224 if (QDF_IS_STATUS_ERROR(ret)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800225 WMA_LOGE("Failed to set IBSS_PS_1RX_CHAIN_IN_ATIM_WINDOW_ENABLE ret=%d",
226 ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530227 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800228 }
229
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530230 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800231}
232#endif /* QCA_IBSS_SUPPORT */
233
234/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800235 * wma_set_ap_peer_uapsd() - set powersave parameters in ap mode to fw
236 * @wma: wma handle
237 * @vdev_id: vdev id
238 * @peer_addr: peer mac address
239 * @uapsd_value: uapsd value
240 * @max_sp: maximum service period
241 *
Govind Singhd76a5b02016-03-08 15:12:14 +0530242 * Return: QDF_STATUS_SUCCESS for success or error code
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800243 */
Govind Singhd76a5b02016-03-08 15:12:14 +0530244QDF_STATUS wma_set_ap_peer_uapsd(tp_wma_handle wma, uint32_t vdev_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800245 uint8_t *peer_addr, uint8_t uapsd_value,
246 uint8_t max_sp)
247{
248 uint32_t uapsd = 0;
249 uint32_t max_sp_len = 0;
Govind Singhd76a5b02016-03-08 15:12:14 +0530250 QDF_STATUS ret;
251 struct ap_ps_params param = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800252
253 if (uapsd_value & UAPSD_VO_ENABLED) {
254 uapsd |= WMI_AP_PS_UAPSD_AC3_DELIVERY_EN |
255 WMI_AP_PS_UAPSD_AC3_TRIGGER_EN;
256 }
257
258 if (uapsd_value & UAPSD_VI_ENABLED) {
259 uapsd |= WMI_AP_PS_UAPSD_AC2_DELIVERY_EN |
260 WMI_AP_PS_UAPSD_AC2_TRIGGER_EN;
261 }
262
263 if (uapsd_value & UAPSD_BK_ENABLED) {
264 uapsd |= WMI_AP_PS_UAPSD_AC1_DELIVERY_EN |
265 WMI_AP_PS_UAPSD_AC1_TRIGGER_EN;
266 }
267
268 if (uapsd_value & UAPSD_BE_ENABLED) {
269 uapsd |= WMI_AP_PS_UAPSD_AC0_DELIVERY_EN |
270 WMI_AP_PS_UAPSD_AC0_TRIGGER_EN;
271 }
272
273 switch (max_sp) {
274 case UAPSD_MAX_SP_LEN_2:
275 max_sp_len = WMI_AP_PS_PEER_PARAM_MAX_SP_2;
276 break;
277 case UAPSD_MAX_SP_LEN_4:
278 max_sp_len = WMI_AP_PS_PEER_PARAM_MAX_SP_4;
279 break;
280 case UAPSD_MAX_SP_LEN_6:
281 max_sp_len = WMI_AP_PS_PEER_PARAM_MAX_SP_6;
282 break;
283 default:
284 max_sp_len = WMI_AP_PS_PEER_PARAM_MAX_SP_UNLIMITED;
285 break;
286 }
287
288 WMA_LOGD("Set WMI_AP_PS_PEER_PARAM_UAPSD 0x%x for %pM",
289 uapsd, peer_addr);
Govind Singhd76a5b02016-03-08 15:12:14 +0530290 param.vdev_id = vdev_id;
291 param.param = WMI_AP_PS_PEER_PARAM_UAPSD;
292 param.value = uapsd;
293 ret = wmi_unified_ap_ps_cmd_send(wma->wmi_handle, peer_addr,
294 &param);
295 if (QDF_IS_STATUS_ERROR(ret)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800296 WMA_LOGE("Failed to set WMI_AP_PS_PEER_PARAM_UAPSD for %pM",
297 peer_addr);
298 return ret;
299 }
300
301 WMA_LOGD("Set WMI_AP_PS_PEER_PARAM_MAX_SP 0x%x for %pM",
302 max_sp_len, peer_addr);
303
Govind Singhd76a5b02016-03-08 15:12:14 +0530304 param.vdev_id = vdev_id;
305 param.param = WMI_AP_PS_PEER_PARAM_MAX_SP;
306 param.value = max_sp_len;
307 ret = wmi_unified_ap_ps_cmd_send(wma->wmi_handle, peer_addr,
308 &param);
309 if (QDF_IS_STATUS_ERROR(ret)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800310 WMA_LOGE("Failed to set WMI_AP_PS_PEER_PARAM_MAX_SP for %pM",
311 peer_addr);
312 return ret;
313 }
Govind Singhd76a5b02016-03-08 15:12:14 +0530314
315 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800316}
317
318/**
319 * wma_update_edca_params_for_ac() - to update per ac EDCA parameters
320 * @edca_param: EDCA parameters
321 * @wmm_param: wmm parameters
322 * @ac: access category
323 *
324 * Return: none
325 */
326void wma_update_edca_params_for_ac(tSirMacEdcaParamRecord *edca_param,
327 wmi_wmm_vparams *wmm_param, int ac)
328{
329#define WMA_WMM_EXPO_TO_VAL(val) ((1 << (val)) - 1)
330 wmm_param->cwmin = WMA_WMM_EXPO_TO_VAL(edca_param->cw.min);
331 wmm_param->cwmax = WMA_WMM_EXPO_TO_VAL(edca_param->cw.max);
332 wmm_param->aifs = edca_param->aci.aifsn;
333 wmm_param->txoplimit = edca_param->txoplimit;
334 wmm_param->acm = edca_param->aci.acm;
335
336 /* TODO: No ack is not present in EdcaParamRecord */
337 wmm_param->no_ack = 0;
338
339 WMA_LOGI("WMM PARAMS AC[%d]: AIFS %d Min %d Max %d TXOP %d ACM %d NOACK %d",
340 ac, wmm_param->aifs, wmm_param->cwmin, wmm_param->cwmax,
341 wmm_param->txoplimit, wmm_param->acm, wmm_param->no_ack);
342}
343
344/**
345 * wma_set_tx_power() - set tx power limit in fw
346 * @handle: wma handle
347 * @tx_pwr_params: tx power parameters
348 *
349 * Return: none
350 */
351void wma_set_tx_power(WMA_HANDLE handle,
352 tMaxTxPowerParams *tx_pwr_params)
353{
354 tp_wma_handle wma_handle = (tp_wma_handle) handle;
355 uint8_t vdev_id;
Govind Singhd76a5b02016-03-08 15:12:14 +0530356 QDF_STATUS ret = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800357 void *pdev;
358
Anurag Chouhan6d760662016-02-20 16:05:43 +0530359 if (tx_pwr_params->dev_mode == QDF_SAP_MODE ||
360 tx_pwr_params->dev_mode == QDF_P2P_GO_MODE) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800361 pdev = wma_find_vdev_by_addr(wma_handle,
Srinivas Girigowda97215232015-09-24 12:26:28 -0700362 tx_pwr_params->bssId.bytes,
363 &vdev_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800364 } else {
365 pdev = wma_find_vdev_by_bssid(wma_handle,
Srinivas Girigowda97215232015-09-24 12:26:28 -0700366 tx_pwr_params->bssId.bytes,
367 &vdev_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800368 }
369 if (!pdev) {
370 WMA_LOGE("vdev handle is invalid for %pM",
Srinivas Girigowda97215232015-09-24 12:26:28 -0700371 tx_pwr_params->bssId.bytes);
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530372 qdf_mem_free(tx_pwr_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800373 return;
374 }
375
376 if (!(wma_handle->interfaces[vdev_id].vdev_up)) {
377 WMA_LOGE("%s: vdev id %d is not up for %pM", __func__, vdev_id,
Srinivas Girigowda97215232015-09-24 12:26:28 -0700378 tx_pwr_params->bssId.bytes);
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530379 qdf_mem_free(tx_pwr_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800380 return;
381 }
382
383 if (tx_pwr_params->power == 0) {
384 /* set to default. Since the app does not care the tx power
385 * we keep the previous setting */
386 wma_handle->interfaces[vdev_id].tx_power = 0;
387 ret = 0;
388 goto end;
389 }
390 if (wma_handle->interfaces[vdev_id].max_tx_power != 0) {
391 /* make sure tx_power less than max_tx_power */
392 if (tx_pwr_params->power >
393 wma_handle->interfaces[vdev_id].max_tx_power) {
394 tx_pwr_params->power =
395 wma_handle->interfaces[vdev_id].max_tx_power;
396 }
397 }
398 if (wma_handle->interfaces[vdev_id].tx_power != tx_pwr_params->power) {
399
400 /* tx_power changed, Push the tx_power to FW */
401 WMA_LOGW("%s: Set TX power limit [WMI_VDEV_PARAM_TX_PWRLIMIT] to %d",
402 __func__, tx_pwr_params->power);
Govind Singhd76a5b02016-03-08 15:12:14 +0530403 ret = wma_vdev_set_param(wma_handle->wmi_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800404 vdev_id,
405 WMI_VDEV_PARAM_TX_PWRLIMIT,
406 tx_pwr_params->power);
Govind Singhd76a5b02016-03-08 15:12:14 +0530407 if (ret == QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800408 wma_handle->interfaces[vdev_id].tx_power =
409 tx_pwr_params->power;
410 } else {
411 /* no tx_power change */
Govind Singhd76a5b02016-03-08 15:12:14 +0530412 ret = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800413 }
414end:
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530415 qdf_mem_free(tx_pwr_params);
Govind Singhd76a5b02016-03-08 15:12:14 +0530416 if (QDF_IS_STATUS_ERROR(ret))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800417 WMA_LOGE("Failed to set vdev param WMI_VDEV_PARAM_TX_PWRLIMIT");
418}
419
420/**
421 * wma_set_max_tx_power() - set max tx power limit in fw
422 * @handle: wma handle
423 * @tx_pwr_params: tx power parameters
424 *
425 * Return: none
426 */
427void wma_set_max_tx_power(WMA_HANDLE handle,
428 tMaxTxPowerParams *tx_pwr_params)
429{
430 tp_wma_handle wma_handle = (tp_wma_handle) handle;
431 uint8_t vdev_id;
Govind Singhd76a5b02016-03-08 15:12:14 +0530432 QDF_STATUS ret = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800433 void *pdev;
Amar Singhala297bfa2015-10-15 15:07:29 -0700434 int8_t prev_max_power;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800435
Srinivas Girigowda97215232015-09-24 12:26:28 -0700436 pdev = wma_find_vdev_by_addr(wma_handle, tx_pwr_params->bssId.bytes,
437 &vdev_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800438 if (pdev == NULL) {
439 /* not in SAP array. Try the station/p2p array */
440 pdev = wma_find_vdev_by_bssid(wma_handle,
Srinivas Girigowda97215232015-09-24 12:26:28 -0700441 tx_pwr_params->bssId.bytes,
442 &vdev_id);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800443 }
444 if (!pdev) {
445 WMA_LOGE("vdev handle is invalid for %pM",
Srinivas Girigowda97215232015-09-24 12:26:28 -0700446 tx_pwr_params->bssId.bytes);
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530447 qdf_mem_free(tx_pwr_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800448 return;
449 }
450
451 if (!(wma_handle->interfaces[vdev_id].vdev_up)) {
452 WMA_LOGE("%s: vdev id %d is not up", __func__, vdev_id);
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530453 qdf_mem_free(tx_pwr_params);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800454 return;
455 }
456
457 if (wma_handle->interfaces[vdev_id].max_tx_power ==
458 tx_pwr_params->power) {
Govind Singhd76a5b02016-03-08 15:12:14 +0530459 ret = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800460 goto end;
461 }
462 prev_max_power = wma_handle->interfaces[vdev_id].max_tx_power;
463 wma_handle->interfaces[vdev_id].max_tx_power = tx_pwr_params->power;
464 if (wma_handle->interfaces[vdev_id].max_tx_power == 0) {
Govind Singhd76a5b02016-03-08 15:12:14 +0530465 ret = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800466 goto end;
467 }
468 WMA_LOGW("Set MAX TX power limit [WMI_VDEV_PARAM_TX_PWRLIMIT] to %d",
469 wma_handle->interfaces[vdev_id].max_tx_power);
Govind Singhd76a5b02016-03-08 15:12:14 +0530470 ret = wma_vdev_set_param(wma_handle->wmi_handle, vdev_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800471 WMI_VDEV_PARAM_TX_PWRLIMIT,
472 wma_handle->interfaces[vdev_id].max_tx_power);
Govind Singhd76a5b02016-03-08 15:12:14 +0530473 if (ret == QDF_STATUS_SUCCESS)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800474 wma_handle->interfaces[vdev_id].tx_power =
475 wma_handle->interfaces[vdev_id].max_tx_power;
476 else
477 wma_handle->interfaces[vdev_id].max_tx_power = prev_max_power;
478end:
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530479 qdf_mem_free(tx_pwr_params);
Govind Singhd76a5b02016-03-08 15:12:14 +0530480 if (QDF_IS_STATUS_ERROR(ret))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800481 WMA_LOGE("%s: Failed to set vdev param WMI_VDEV_PARAM_TX_PWRLIMIT",
482 __func__);
483}
484
485/**
486 * wmi_unified_set_sta_ps() - set sta powersave params in fw
487 * @handle: wma handle
488 * @vdev_id: vdev id
489 * @val: value
490 *
Govind Singh09c3b492016-03-08 16:05:14 +0530491 * Return: QDF_STATUS_SUCCESS for success or error code
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800492 */
Govind Singh09c3b492016-03-08 16:05:14 +0530493QDF_STATUS wmi_unified_set_sta_ps(wmi_unified_t wmi_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800494 uint32_t vdev_id, uint8_t val)
495{
Govind Singh09c3b492016-03-08 16:05:14 +0530496 QDF_STATUS ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800497
Govind Singh09c3b492016-03-08 16:05:14 +0530498 ret = wmi_unified_set_sta_ps_mode(wmi_handle, vdev_id,
499 val);
500 if (QDF_IS_STATUS_ERROR(ret))
501 WMA_LOGE("Failed to send set Mimo PS ret = %d", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800502
Govind Singh09c3b492016-03-08 16:05:14 +0530503 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800504}
505
506/**
507 * wma_get_uapsd_mask() - get uapsd mask based on uapsd parameters
508 * @uapsd_params: uapsed parameters
509 *
510 * Return: uapsd mask
511 */
512static inline uint32_t wma_get_uapsd_mask(tpUapsd_Params uapsd_params)
513{
514 uint32_t uapsd_val = 0;
515
516 if (uapsd_params->beDeliveryEnabled)
517 uapsd_val |= WMI_STA_PS_UAPSD_AC0_DELIVERY_EN;
518
519 if (uapsd_params->beTriggerEnabled)
520 uapsd_val |= WMI_STA_PS_UAPSD_AC0_TRIGGER_EN;
521
522 if (uapsd_params->bkDeliveryEnabled)
523 uapsd_val |= WMI_STA_PS_UAPSD_AC1_DELIVERY_EN;
524
525 if (uapsd_params->bkTriggerEnabled)
526 uapsd_val |= WMI_STA_PS_UAPSD_AC1_TRIGGER_EN;
527
528 if (uapsd_params->viDeliveryEnabled)
529 uapsd_val |= WMI_STA_PS_UAPSD_AC2_DELIVERY_EN;
530
531 if (uapsd_params->viTriggerEnabled)
532 uapsd_val |= WMI_STA_PS_UAPSD_AC2_TRIGGER_EN;
533
534 if (uapsd_params->voDeliveryEnabled)
535 uapsd_val |= WMI_STA_PS_UAPSD_AC3_DELIVERY_EN;
536
537 if (uapsd_params->voTriggerEnabled)
538 uapsd_val |= WMI_STA_PS_UAPSD_AC3_TRIGGER_EN;
539
540 return uapsd_val;
541}
542
543/**
544 * wma_set_force_sleep() - set power save parameters to fw
545 * @wma: wma handle
546 * @vdev_id: vdev id
547 * @enable: enable/disable
548 * @qpower_config: qpower configuration
549 *
Govind Singhd76a5b02016-03-08 15:12:14 +0530550 * Return: QDF_STATUS_SUCCESS for success or error code
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800551 */
Govind Singhd76a5b02016-03-08 15:12:14 +0530552static QDF_STATUS wma_set_force_sleep(tp_wma_handle wma,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800553 uint32_t vdev_id,
554 uint8_t enable,
555 enum powersave_qpower_mode qpower_config)
556{
Govind Singhd76a5b02016-03-08 15:12:14 +0530557 QDF_STATUS ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800558 uint32_t cfg_data_val = 0;
559 /* get mac to acess CFG data base */
Anurag Chouhan6d760662016-02-20 16:05:43 +0530560 struct sAniSirGlobal *mac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800561 uint32_t rx_wake_policy;
562 uint32_t tx_wake_threshold;
563 uint32_t pspoll_count;
564 uint32_t inactivity_time;
565 uint32_t psmode;
566
567 WMA_LOGD("Set Force Sleep vdevId %d val %d", vdev_id, enable);
568
569 if (NULL == mac) {
570 WMA_LOGE("%s: Unable to get PE context", __func__);
Govind Singhd76a5b02016-03-08 15:12:14 +0530571 return QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800572 }
573
574 /* Set Tx/Rx Data InActivity Timeout */
575 if (wlan_cfg_get_int(mac, WNI_CFG_PS_DATA_INACTIVITY_TIMEOUT,
576 &cfg_data_val) != eSIR_SUCCESS) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530577 QDF_TRACE(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800578 "Failed to get WNI_CFG_PS_DATA_INACTIVITY_TIMEOUT");
579 cfg_data_val = POWERSAVE_DEFAULT_INACTIVITY_TIME;
580 }
581 inactivity_time = (uint32_t) cfg_data_val;
582
583 if (enable) {
584 /* override normal configuration and force station asleep */
585 rx_wake_policy = WMI_STA_PS_RX_WAKE_POLICY_POLL_UAPSD;
586 tx_wake_threshold = WMI_STA_PS_TX_WAKE_THRESHOLD_NEVER;
587
588 if (wlan_cfg_get_int(mac, WNI_CFG_MAX_PS_POLL,
589 &cfg_data_val) != eSIR_SUCCESS) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530590 QDF_TRACE(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800591 "Failed to get value for WNI_CFG_MAX_PS_POLL");
592 }
593 if (cfg_data_val)
594 pspoll_count = (uint32_t) cfg_data_val;
595 else
596 pspoll_count = WMA_DEFAULT_MAX_PSPOLL_BEFORE_WAKE;
597
598 psmode = WMI_STA_PS_MODE_ENABLED;
599 } else {
600 /* Ps Poll Wake Policy */
601 if (wlan_cfg_get_int(mac, WNI_CFG_MAX_PS_POLL,
602 &cfg_data_val) != eSIR_SUCCESS) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530603 QDF_TRACE(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800604 "Failed to get value for WNI_CFG_MAX_PS_POLL");
605 }
606 if (cfg_data_val) {
607 /* Ps Poll is enabled */
608 rx_wake_policy = WMI_STA_PS_RX_WAKE_POLICY_POLL_UAPSD;
609 pspoll_count = (uint32_t) cfg_data_val;
610 tx_wake_threshold = WMI_STA_PS_TX_WAKE_THRESHOLD_NEVER;
611 } else {
612 rx_wake_policy = WMI_STA_PS_RX_WAKE_POLICY_WAKE;
613 pspoll_count = WMI_STA_PS_PSPOLL_COUNT_NO_MAX;
614 tx_wake_threshold = WMI_STA_PS_TX_WAKE_THRESHOLD_ALWAYS;
615 }
616 psmode = WMI_STA_PS_MODE_ENABLED;
617 }
618
619 /*
620 * QPower is enabled by default in Firmware
621 * So Disable QPower explicitly
622 */
Govind Singhd76a5b02016-03-08 15:12:14 +0530623 ret = wma_unified_set_sta_ps_param(wma->wmi_handle, vdev_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800624 WMI_STA_PS_ENABLE_QPOWER,
625 qpower_config);
Govind Singhd76a5b02016-03-08 15:12:14 +0530626 if (QDF_IS_STATUS_ERROR(ret)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800627 WMA_LOGE("Disable QPower Failed vdevId %d", vdev_id);
628 return ret;
629 }
630 WMA_LOGD("QPower Disabled vdevId %d", vdev_id);
631
632 /* Set the Wake Policy to WMI_STA_PS_RX_WAKE_POLICY_POLL_UAPSD */
Govind Singhd76a5b02016-03-08 15:12:14 +0530633 ret = wma_unified_set_sta_ps_param(wma->wmi_handle, vdev_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800634 WMI_STA_PS_PARAM_RX_WAKE_POLICY,
635 rx_wake_policy);
636
Govind Singhd76a5b02016-03-08 15:12:14 +0530637 if (QDF_IS_STATUS_ERROR(ret)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800638 WMA_LOGE("Setting wake policy Failed vdevId %d", vdev_id);
639 return ret;
640 }
641 WMA_LOGD("Setting wake policy to %d vdevId %d",
642 rx_wake_policy, vdev_id);
643
644 /* Set the Tx Wake Threshold */
Govind Singhd76a5b02016-03-08 15:12:14 +0530645 ret = wma_unified_set_sta_ps_param(wma->wmi_handle, vdev_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800646 WMI_STA_PS_PARAM_TX_WAKE_THRESHOLD,
647 tx_wake_threshold);
648
Govind Singhd76a5b02016-03-08 15:12:14 +0530649 if (QDF_IS_STATUS_ERROR(ret)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800650 WMA_LOGE("Setting TxWake Threshold vdevId %d", vdev_id);
651 return ret;
652 }
653 WMA_LOGD("Setting TxWake Threshold to %d vdevId %d",
654 tx_wake_threshold, vdev_id);
655
656 /* Set the Ps Poll Count */
Govind Singhd76a5b02016-03-08 15:12:14 +0530657 ret = wma_unified_set_sta_ps_param(wma->wmi_handle, vdev_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800658 WMI_STA_PS_PARAM_PSPOLL_COUNT,
659 pspoll_count);
660
Govind Singhd76a5b02016-03-08 15:12:14 +0530661 if (QDF_IS_STATUS_ERROR(ret)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800662 WMA_LOGE("Set Ps Poll Count Failed vdevId %d ps poll cnt %d",
663 vdev_id, pspoll_count);
664 return ret;
665 }
666 WMA_LOGD("Set Ps Poll Count vdevId %d ps poll cnt %d",
667 vdev_id, pspoll_count);
668
669 /* Set the Tx/Rx InActivity */
Govind Singhd76a5b02016-03-08 15:12:14 +0530670 ret = wma_unified_set_sta_ps_param(wma->wmi_handle, vdev_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800671 WMI_STA_PS_PARAM_INACTIVITY_TIME,
672 inactivity_time);
673
Govind Singhd76a5b02016-03-08 15:12:14 +0530674 if (QDF_IS_STATUS_ERROR(ret)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800675 WMA_LOGE("Setting Tx/Rx InActivity Failed vdevId %d InAct %d",
676 vdev_id, inactivity_time);
677 return ret;
678 }
679 WMA_LOGD("Set Tx/Rx InActivity vdevId %d InAct %d",
680 vdev_id, inactivity_time);
681
682 /* Enable Sta Mode Power save */
683 ret = wmi_unified_set_sta_ps(wma->wmi_handle, vdev_id, true);
684
Govind Singhd76a5b02016-03-08 15:12:14 +0530685 if (QDF_IS_STATUS_ERROR(ret)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800686 WMA_LOGE("Enable Sta Mode Ps Failed vdevId %d", vdev_id);
687 return ret;
688 }
689
690 /* Set Listen Interval */
691 if (wlan_cfg_get_int(mac, WNI_CFG_LISTEN_INTERVAL,
692 &cfg_data_val) != eSIR_SUCCESS) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530693 QDF_TRACE(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800694 "Failed to get value for WNI_CFG_LISTEN_INTERVAL");
695 cfg_data_val = POWERSAVE_DEFAULT_LISTEN_INTERVAL;
696 }
697
Govind Singhd76a5b02016-03-08 15:12:14 +0530698 ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800699 WMI_VDEV_PARAM_LISTEN_INTERVAL,
700 cfg_data_val);
Govind Singhd76a5b02016-03-08 15:12:14 +0530701 if (QDF_IS_STATUS_ERROR(ret)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800702 /* Even it fails continue Fw will take default LI */
703 WMA_LOGE("Failed to Set Listen Interval vdevId %d", vdev_id);
704 }
705 WMA_LOGD("Set Listen Interval vdevId %d Listen Intv %d",
706 vdev_id, cfg_data_val);
Govind Singhd76a5b02016-03-08 15:12:14 +0530707
708 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800709}
710
711/**
712 * wma_set_qpower_force_sleep() - set qpower params in fw
713 * @wma: wma handle
714 * @vdev_id: vdev id
715 * @enable: value
716 *
Govind Singhd76a5b02016-03-08 15:12:14 +0530717 * Return: QDF_STATUS_SUCCESS for success or error code
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800718 */
Govind Singhd76a5b02016-03-08 15:12:14 +0530719QDF_STATUS wma_set_qpower_force_sleep(tp_wma_handle wma, uint32_t vdev_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800720 uint8_t enable)
721{
Govind Singhd76a5b02016-03-08 15:12:14 +0530722 QDF_STATUS ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800723 uint32_t cfg_data_val = 0;
724 /* get mac to acess CFG data base */
Anurag Chouhan6d760662016-02-20 16:05:43 +0530725 struct sAniSirGlobal *mac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800726 uint32_t pspoll_count = WMA_DEFAULT_MAX_PSPOLL_BEFORE_WAKE;
727
728 WMA_LOGE("Set QPower Force(1)/Normal(0) Sleep vdevId %d val %d",
729 vdev_id, enable);
730
731 if (NULL == mac) {
732 WMA_LOGE("%s: Unable to get PE context", __func__);
Govind Singhd76a5b02016-03-08 15:12:14 +0530733 return QDF_STATUS_E_NOMEM;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800734 }
735
736 /* Get Configured Ps Poll Count */
737 if (wlan_cfg_get_int(mac, WNI_CFG_MAX_PS_POLL,
738 &cfg_data_val) != eSIR_SUCCESS) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530739 QDF_TRACE(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800740 "Failed to get value for WNI_CFG_MAX_PS_POLL");
741 }
742 if (cfg_data_val) {
743 pspoll_count = (uint32_t) cfg_data_val;
744 }
745
746 /* Enable QPower */
Govind Singhd76a5b02016-03-08 15:12:14 +0530747 ret = wma_unified_set_sta_ps_param(wma->wmi_handle, vdev_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800748 WMI_STA_PS_ENABLE_QPOWER, 1);
749
Govind Singhd76a5b02016-03-08 15:12:14 +0530750 if (QDF_IS_STATUS_ERROR(ret)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800751 WMA_LOGE("Enable QPower Failed vdevId %d", vdev_id);
752 return ret;
753 }
754 WMA_LOGD("QPower Enabled vdevId %d", vdev_id);
755
756 /* Set the Wake Policy to WMI_STA_PS_RX_WAKE_POLICY_POLL_UAPSD */
Govind Singhd76a5b02016-03-08 15:12:14 +0530757 ret = wma_unified_set_sta_ps_param(wma->wmi_handle, vdev_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800758 WMI_STA_PS_PARAM_RX_WAKE_POLICY,
759 WMI_STA_PS_RX_WAKE_POLICY_POLL_UAPSD);
760
Govind Singhd76a5b02016-03-08 15:12:14 +0530761 if (QDF_IS_STATUS_ERROR(ret)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800762 WMA_LOGE("Setting wake policy to pspoll/uapsd Failed vdevId %d",
763 vdev_id);
764 return ret;
765 }
766 WMA_LOGD("Wake policy set to to pspoll/uapsd vdevId %d", vdev_id);
767
768 if (enable) {
769 /* Set the Tx Wake Threshold */
Govind Singhd76a5b02016-03-08 15:12:14 +0530770 ret = wma_unified_set_sta_ps_param(wma->wmi_handle, vdev_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800771 WMI_STA_PS_PARAM_TX_WAKE_THRESHOLD,
772 WMI_STA_PS_TX_WAKE_THRESHOLD_NEVER);
773
Govind Singhd76a5b02016-03-08 15:12:14 +0530774 if (QDF_IS_STATUS_ERROR(ret)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800775 WMA_LOGE("Setting TxWake Threshold vdevId %d", vdev_id);
776 return ret;
777 }
778 WMA_LOGD("TxWake Threshold set to TX_WAKE_THRESHOLD_NEVER %d",
779 vdev_id);
780 }
781
782 /* Set the QPower Ps Poll Count */
Govind Singhd76a5b02016-03-08 15:12:14 +0530783 ret = wma_unified_set_sta_ps_param(wma->wmi_handle, vdev_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800784 WMI_STA_PS_PARAM_QPOWER_PSPOLL_COUNT,
785 pspoll_count);
786
Govind Singhd76a5b02016-03-08 15:12:14 +0530787 if (QDF_IS_STATUS_ERROR(ret)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800788 WMA_LOGE("Set QPower Ps Poll Count Failed vdevId %d ps poll cnt %d",
789 vdev_id, pspoll_count);
790 return ret;
791 }
792 WMA_LOGD("Set QPower Ps Poll Count vdevId %d ps poll cnt %d",
793 vdev_id, pspoll_count);
794
795 /* Enable Sta Mode Power save */
796 ret = wmi_unified_set_sta_ps(wma->wmi_handle, vdev_id, true);
797
Govind Singhd76a5b02016-03-08 15:12:14 +0530798 if (QDF_IS_STATUS_ERROR(ret)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800799 WMA_LOGE("Enable Sta Mode Ps Failed vdevId %d", vdev_id);
800 return ret;
801 }
802
803 /* Set Listen Interval */
804 if (wlan_cfg_get_int(mac, WNI_CFG_LISTEN_INTERVAL,
805 &cfg_data_val) != eSIR_SUCCESS) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +0530806 QDF_TRACE(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800807 "Failed to get value for WNI_CFG_LISTEN_INTERVAL");
808 cfg_data_val = POWERSAVE_DEFAULT_LISTEN_INTERVAL;
809 }
810
Govind Singhd76a5b02016-03-08 15:12:14 +0530811 ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800812 WMI_VDEV_PARAM_LISTEN_INTERVAL,
813 cfg_data_val);
Govind Singhd76a5b02016-03-08 15:12:14 +0530814 if (QDF_IS_STATUS_ERROR(ret)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800815 /* Even it fails continue Fw will take default LI */
816 WMA_LOGE("Failed to Set Listen Interval vdevId %d", vdev_id);
817 }
818 WMA_LOGD("Set Listen Interval vdevId %d Listen Intv %d",
819 vdev_id, cfg_data_val);
Govind Singhd76a5b02016-03-08 15:12:14 +0530820
821 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800822}
823
824/**
825 * wma_get_qpower_config() - get qpower configuration
826 * @wma: WMA handle
827 *
828 * Power Save Offload configuration:
829 * 0 -> Power save offload is disabled
830 * 1 -> Legacy Power save enabled + Deep sleep Disabled
831 * 2 -> QPower enabled + Deep sleep Disabled
832 * 3 -> Legacy Power save enabled + Deep sleep Enabled
833 * 4 -> QPower enabled + Deep sleep Enabled
834 * 5 -> Duty cycling QPower enabled
835 *
836 * Return: enum powersave_qpower_mode with below values
837 * QPOWER_DISABLED if QPOWER is disabled
838 * QPOWER_ENABLED if QPOWER is enabled
839 * QPOWER_DUTY_CYCLING if DUTY CYCLING QPOWER is enabled
840 */
841static enum powersave_qpower_mode wma_get_qpower_config(tp_wma_handle wma)
842{
843 switch (wma->powersave_mode) {
844 case PS_QPOWER_NODEEPSLEEP:
845 case PS_QPOWER_DEEPSLEEP:
846 WMA_LOGI("QPOWER is enabled in power save mode %d",
847 wma->powersave_mode);
848 return QPOWER_ENABLED;
849 case PS_DUTY_CYCLING_QPOWER:
850 WMA_LOGI("DUTY cycling QPOWER is enabled in power save mode %d",
851 wma->powersave_mode);
852 return QPOWER_DUTY_CYCLING;
853
854 default:
855 WMA_LOGI("QPOWER is disabled in power save mode %d",
856 wma->powersave_mode);
857 return QPOWER_DISABLED;
858 }
859}
860
861/**
862 * wma_enable_sta_ps_mode() - enable sta powersave params in fw
863 * @wma: wma handle
864 * @ps_req: power save request
865 *
866 * Return: none
867 */
868void wma_enable_sta_ps_mode(tp_wma_handle wma, tpEnablePsParams ps_req)
869{
870 uint32_t vdev_id = ps_req->sessionid;
Govind Singhd76a5b02016-03-08 15:12:14 +0530871 QDF_STATUS ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800872 enum powersave_qpower_mode qpower_config = wma_get_qpower_config(wma);
873 struct wma_txrx_node *iface = &wma->interfaces[vdev_id];
Govind Singhd76a5b02016-03-08 15:12:14 +0530874
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800875 if (!iface->handle) {
876 WMA_LOGE("vdev id %d is not active", vdev_id);
877 return;
878 }
879 if (eSIR_ADDON_NOTHING == ps_req->psSetting) {
880 WMA_LOGD("Enable Sta Mode Ps vdevId %d", vdev_id);
Govind Singhd76a5b02016-03-08 15:12:14 +0530881 ret = wma_unified_set_sta_ps_param(wma->wmi_handle, vdev_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800882 WMI_STA_PS_PARAM_UAPSD, 0);
Govind Singhd76a5b02016-03-08 15:12:14 +0530883 if (QDF_IS_STATUS_ERROR(ret)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800884 WMA_LOGE("Set Uapsd param 0 Failed vdevId %d", vdev_id);
885 return;
886 }
887
888 ret = wma_set_force_sleep(wma, vdev_id, false,
889 qpower_config);
Govind Singhd76a5b02016-03-08 15:12:14 +0530890 if (QDF_IS_STATUS_ERROR(ret)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800891 WMA_LOGE("Enable Sta Ps Failed vdevId %d", vdev_id);
892 return;
893 }
894 } else if (eSIR_ADDON_ENABLE_UAPSD == ps_req->psSetting) {
895 uint32_t uapsd_val = 0;
896 uapsd_val = wma_get_uapsd_mask(&ps_req->uapsdParams);
897
898 if (uapsd_val != iface->uapsd_cached_val) {
899 WMA_LOGD("Enable Uapsd vdevId %d Mask %d",
900 vdev_id, uapsd_val);
Govind Singhd76a5b02016-03-08 15:12:14 +0530901 ret = wma_unified_set_sta_ps_param(wma->wmi_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800902 vdev_id,
903 WMI_STA_PS_PARAM_UAPSD,
904 uapsd_val);
Govind Singhd76a5b02016-03-08 15:12:14 +0530905 if (QDF_IS_STATUS_ERROR(ret)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800906 WMA_LOGE("Enable Uapsd Failed vdevId %d",
907 vdev_id);
908 return;
909 }
910 /* Cache the Uapsd Mask */
911 iface->uapsd_cached_val = uapsd_val;
912 } else {
913 WMA_LOGD("Already Uapsd Enabled vdevId %d Mask %d",
914 vdev_id, uapsd_val);
915 }
916
917 WMA_LOGD("Enable Forced Sleep vdevId %d", vdev_id);
918 ret = wma_set_force_sleep(wma, vdev_id, true,
919 qpower_config);
920
Govind Singhd76a5b02016-03-08 15:12:14 +0530921 if (QDF_IS_STATUS_ERROR(ret)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800922 WMA_LOGE("Enable Forced Sleep Failed vdevId %d",
923 vdev_id);
924 return;
925 }
926 }
927 iface->dtimPeriod = ps_req->bcnDtimPeriod;
928}
929
930/**
931 * wma_disable_sta_ps_mode() - disable sta powersave params in fw
932 * @wma: wma handle
933 * @ps_req: power save request
934 *
935 * Return: none
936 */
937void wma_disable_sta_ps_mode(tp_wma_handle wma, tpDisablePsParams ps_req)
938{
Govind Singhd76a5b02016-03-08 15:12:14 +0530939 QDF_STATUS ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800940 uint32_t vdev_id = ps_req->sessionid;
941
942 WMA_LOGD("Disable Sta Mode Ps vdevId %d", vdev_id);
943
944 /* Disable Sta Mode Power save */
945 ret = wmi_unified_set_sta_ps(wma->wmi_handle, vdev_id, false);
Govind Singhd76a5b02016-03-08 15:12:14 +0530946 if (QDF_IS_STATUS_ERROR(ret)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800947 WMA_LOGE("Disable Sta Mode Ps Failed vdevId %d", vdev_id);
948 return;
949 }
950
951 /* Disable UAPSD incase if additional Req came */
952 if (eSIR_ADDON_DISABLE_UAPSD == ps_req->psSetting) {
953 WMA_LOGD("Disable Uapsd vdevId %d", vdev_id);
Govind Singhd76a5b02016-03-08 15:12:14 +0530954 ret = wma_unified_set_sta_ps_param(wma->wmi_handle, vdev_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800955 WMI_STA_PS_PARAM_UAPSD, 0);
Govind Singhd76a5b02016-03-08 15:12:14 +0530956 if (QDF_IS_STATUS_ERROR(ret)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800957 WMA_LOGE("Disable Uapsd Failed vdevId %d", vdev_id);
958 /*
959 * Even this fails we can proceed as success
960 * since we disabled powersave
961 */
962 }
963 }
964}
965
966/**
967 * wma_enable_uapsd_mode() - enable uapsd mode in fw
968 * @wma: wma handle
969 * @ps_req: power save request
970 *
971 * Return: none
972 */
973void wma_enable_uapsd_mode(tp_wma_handle wma, tpEnableUapsdParams ps_req)
974{
Govind Singhd76a5b02016-03-08 15:12:14 +0530975 QDF_STATUS ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800976 uint32_t vdev_id = ps_req->sessionid;
977 uint32_t uapsd_val = 0;
978 enum powersave_qpower_mode qpower_config = wma_get_qpower_config(wma);
979
980 /* Disable Sta Mode Power save */
981 ret = wmi_unified_set_sta_ps(wma->wmi_handle, vdev_id, false);
Govind Singhd76a5b02016-03-08 15:12:14 +0530982 if (QDF_IS_STATUS_ERROR(ret)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800983 WMA_LOGE("Disable Sta Mode Ps Failed vdevId %d", vdev_id);
984 return;
985 }
986
987 uapsd_val = wma_get_uapsd_mask(&ps_req->uapsdParams);
988
989 WMA_LOGD("Enable Uapsd vdevId %d Mask %d", vdev_id, uapsd_val);
Govind Singhd76a5b02016-03-08 15:12:14 +0530990 ret = wma_unified_set_sta_ps_param(wma->wmi_handle, vdev_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800991 WMI_STA_PS_PARAM_UAPSD, uapsd_val);
Govind Singhd76a5b02016-03-08 15:12:14 +0530992 if (QDF_IS_STATUS_ERROR(ret)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800993 WMA_LOGE("Enable Uapsd Failed vdevId %d", vdev_id);
994 return;
995 }
996
997 WMA_LOGD("Enable Forced Sleep vdevId %d", vdev_id);
998 ret = wma_set_force_sleep(wma, vdev_id, true,
999 qpower_config);
Govind Singhd76a5b02016-03-08 15:12:14 +05301000 if (QDF_IS_STATUS_ERROR(ret)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001001 WMA_LOGE("Enable Forced Sleep Failed vdevId %d", vdev_id);
1002 return;
1003 }
1004
1005}
1006
1007/**
1008 * wma_disable_uapsd_mode() - disable uapsd mode in fw
1009 * @wma: wma handle
1010 * @ps_req: power save request
1011 *
1012 * Return: none
1013 */
1014void wma_disable_uapsd_mode(tp_wma_handle wma,
1015 tpDisableUapsdParams ps_req)
1016{
Govind Singhd76a5b02016-03-08 15:12:14 +05301017 QDF_STATUS ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001018 uint32_t vdev_id = ps_req->sessionid;
1019 enum powersave_qpower_mode qpower_config = wma_get_qpower_config(wma);
1020
1021 WMA_LOGD("Disable Uapsd vdevId %d", vdev_id);
1022
1023 /* Disable Sta Mode Power save */
1024 ret = wmi_unified_set_sta_ps(wma->wmi_handle, vdev_id, false);
Govind Singhd76a5b02016-03-08 15:12:14 +05301025 if (QDF_IS_STATUS_ERROR(ret)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001026 WMA_LOGE("Disable Sta Mode Ps Failed vdevId %d", vdev_id);
1027 return;
1028 }
1029
Govind Singhd76a5b02016-03-08 15:12:14 +05301030 ret = wma_unified_set_sta_ps_param(wma->wmi_handle, vdev_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001031 WMI_STA_PS_PARAM_UAPSD, 0);
Govind Singhd76a5b02016-03-08 15:12:14 +05301032 if (QDF_IS_STATUS_ERROR(ret)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001033 WMA_LOGE("Disable Uapsd Failed vdevId %d", vdev_id);
1034 return;
1035 }
1036
1037 /* Re enable Sta Mode Powersave with proper configuration */
1038 ret = wma_set_force_sleep(wma, vdev_id, false,
1039 qpower_config);
Govind Singhd76a5b02016-03-08 15:12:14 +05301040 if (QDF_IS_STATUS_ERROR(ret)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001041 WMA_LOGE("Disable Forced Sleep Failed vdevId %d", vdev_id);
1042 return;
1043 }
1044}
1045
1046/**
Govind Singh09c3b492016-03-08 16:05:14 +05301047 * wma_set_sta_uapsd_auto_trig_cmd() - set uapsd auto trigger command
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001048 * @wmi_handle: wma handle
1049 * @vdevid: vdev id
1050 * @peer_addr: peer mac address
1051 * @autoTriggerparam: auto trigger parameters
1052 * @num_ac: number of access category
1053 *
1054 * This function sets the trigger
1055 * uapsd params such as service interval, delay interval
1056 * and suspend interval which will be used by the firmware
1057 * to send trigger frames periodically when there is no
1058 * traffic on the transmit side.
1059 *
1060 * Return: 0 for success or error code.
1061 */
Govind Singh09c3b492016-03-08 16:05:14 +05301062static QDF_STATUS wma_set_sta_uapsd_auto_trig_cmd(wmi_unified_t wmi_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001063 uint32_t vdevid,
1064 uint8_t peer_addr[IEEE80211_ADDR_LEN],
1065 uint8_t *autoTriggerparam,
1066 uint32_t num_ac)
1067{
Govind Singh09c3b492016-03-08 16:05:14 +05301068 QDF_STATUS ret;
1069 struct sta_uapsd_trig_params cmd = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001070
Govind Singh09c3b492016-03-08 16:05:14 +05301071 cmd.vdevid = vdevid;
1072 cmd.auto_triggerparam = autoTriggerparam;
1073 cmd.num_ac = num_ac;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001074
Govind Singh09c3b492016-03-08 16:05:14 +05301075 qdf_mem_copy((uint8_t *) cmd.peer_addr, (uint8_t *) peer_addr,
1076 sizeof(peer_addr));
1077 ret = wmi_unified_set_sta_uapsd_auto_trig_cmd(wmi_handle,
1078 &cmd);
1079 if (QDF_IS_STATUS_ERROR(ret))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001080 WMA_LOGE("Failed to send set uapsd param ret = %d", ret);
Govind Singh09c3b492016-03-08 16:05:14 +05301081
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001082 return ret;
1083}
1084
1085/**
1086 * wma_trigger_uapsd_params() - set trigger uapsd parameter
1087 * @wmi_handle: wma handle
1088 * @vdev_id: vdev id
1089 * @trigger_uapsd_params: trigger uapsd parameters
1090 *
1091 * This function sets the trigger uapsd
1092 * params such as service interval, delay
1093 * interval and suspend interval which
1094 * will be used by the firmware to send
1095 * trigger frames periodically when there
1096 * is no traffic on the transmit side.
1097 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301098 * Return: QDF_STATUS_SUCCESS for success or error code.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001099 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301100QDF_STATUS wma_trigger_uapsd_params(tp_wma_handle wma_handle, uint32_t vdev_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001101 tp_wma_trigger_uapsd_params
1102 trigger_uapsd_params)
1103{
Govind Singh09c3b492016-03-08 16:05:14 +05301104 QDF_STATUS ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001105 wmi_sta_uapsd_auto_trig_param uapsd_trigger_param;
1106
1107 WMA_LOGD("Trigger uapsd params vdev id %d", vdev_id);
1108
1109 WMA_LOGD("WMM AC %d User Priority %d SvcIntv %d DelIntv %d SusIntv %d",
1110 trigger_uapsd_params->wmm_ac,
1111 trigger_uapsd_params->user_priority,
1112 trigger_uapsd_params->service_interval,
1113 trigger_uapsd_params->delay_interval,
1114 trigger_uapsd_params->suspend_interval);
1115
1116 if (!WMI_SERVICE_IS_ENABLED(wma_handle->wmi_service_bitmap,
1117 WMI_STA_UAPSD_BASIC_AUTO_TRIG) ||
1118 !WMI_SERVICE_IS_ENABLED(wma_handle->wmi_service_bitmap,
1119 WMI_STA_UAPSD_VAR_AUTO_TRIG)) {
1120 WMA_LOGD("Trigger uapsd is not supported vdev id %d", vdev_id);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301121 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001122 }
1123
1124 uapsd_trigger_param.wmm_ac = trigger_uapsd_params->wmm_ac;
1125 uapsd_trigger_param.user_priority = trigger_uapsd_params->user_priority;
1126 uapsd_trigger_param.service_interval =
1127 trigger_uapsd_params->service_interval;
1128 uapsd_trigger_param.suspend_interval =
1129 trigger_uapsd_params->suspend_interval;
1130 uapsd_trigger_param.delay_interval =
1131 trigger_uapsd_params->delay_interval;
1132
Govind Singh09c3b492016-03-08 16:05:14 +05301133 ret = wma_set_sta_uapsd_auto_trig_cmd(wma_handle->wmi_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001134 vdev_id, wma_handle->interfaces[vdev_id].bssid,
1135 (uint8_t *) (&uapsd_trigger_param), 1);
Govind Singh09c3b492016-03-08 16:05:14 +05301136 if (QDF_IS_STATUS_ERROR(ret)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001137 WMA_LOGE("Fail to send uapsd param cmd for vdevid %d ret = %d",
1138 ret, vdev_id);
Govind Singh09c3b492016-03-08 16:05:14 +05301139 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001140 }
Govind Singh09c3b492016-03-08 16:05:14 +05301141
1142 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001143}
1144
1145/**
1146 * wma_disable_uapsd_per_ac() - disable uapsd per ac
1147 * @wmi_handle: wma handle
1148 * @vdev_id: vdev id
1149 * @ac: access category
1150 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301151 * Return: QDF_STATUS_SUCCESS for success or error code.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001152 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301153QDF_STATUS wma_disable_uapsd_per_ac(tp_wma_handle wma_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001154 uint32_t vdev_id, enum uapsd_ac ac)
1155{
Govind Singh09c3b492016-03-08 16:05:14 +05301156 QDF_STATUS ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001157 struct wma_txrx_node *iface = &wma_handle->interfaces[vdev_id];
1158 wmi_sta_uapsd_auto_trig_param uapsd_trigger_param;
1159 enum uapsd_up user_priority;
1160
1161 WMA_LOGD("Disable Uapsd per ac vdevId %d ac %d", vdev_id, ac);
1162
1163 switch (ac) {
1164 case UAPSD_VO:
1165 iface->uapsd_cached_val &=
1166 ~(WMI_STA_PS_UAPSD_AC3_DELIVERY_EN |
1167 WMI_STA_PS_UAPSD_AC3_TRIGGER_EN);
1168 user_priority = UAPSD_UP_VO;
1169 break;
1170 case UAPSD_VI:
1171 iface->uapsd_cached_val &=
1172 ~(WMI_STA_PS_UAPSD_AC2_DELIVERY_EN |
1173 WMI_STA_PS_UAPSD_AC2_TRIGGER_EN);
1174 user_priority = UAPSD_UP_VI;
1175 break;
1176 case UAPSD_BK:
1177 iface->uapsd_cached_val &=
1178 ~(WMI_STA_PS_UAPSD_AC1_DELIVERY_EN |
1179 WMI_STA_PS_UAPSD_AC1_TRIGGER_EN);
1180 user_priority = UAPSD_UP_BK;
1181 break;
1182 case UAPSD_BE:
1183 iface->uapsd_cached_val &=
1184 ~(WMI_STA_PS_UAPSD_AC0_DELIVERY_EN |
1185 WMI_STA_PS_UAPSD_AC0_TRIGGER_EN);
1186 user_priority = UAPSD_UP_BE;
1187 break;
1188 default:
1189 WMA_LOGE("Invalid AC vdevId %d ac %d", vdev_id, ac);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301190 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001191 }
1192
1193 /*
1194 * Disable Auto Trigger Functionality before
1195 * disabling uapsd for a particular AC
1196 */
1197 uapsd_trigger_param.wmm_ac = ac;
1198 uapsd_trigger_param.user_priority = user_priority;
1199 uapsd_trigger_param.service_interval = 0;
1200 uapsd_trigger_param.suspend_interval = 0;
1201 uapsd_trigger_param.delay_interval = 0;
1202
Govind Singh09c3b492016-03-08 16:05:14 +05301203 ret = wma_set_sta_uapsd_auto_trig_cmd(wma_handle->wmi_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001204 vdev_id, wma_handle->interfaces[vdev_id].bssid,
1205 (uint8_t *)(&uapsd_trigger_param), 1);
Govind Singh09c3b492016-03-08 16:05:14 +05301206 if (QDF_IS_STATUS_ERROR(ret)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001207 WMA_LOGE("Fail to send auto trig cmd for vdevid %d ret = %d",
1208 ret, vdev_id);
Govind Singh09c3b492016-03-08 16:05:14 +05301209 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001210 }
1211
Govind Singhd76a5b02016-03-08 15:12:14 +05301212 ret = wma_unified_set_sta_ps_param(wma_handle->wmi_handle, vdev_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001213 WMI_STA_PS_PARAM_UAPSD,
1214 iface->uapsd_cached_val);
Govind Singh09c3b492016-03-08 16:05:14 +05301215 if (QDF_IS_STATUS_ERROR(ret)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001216 WMA_LOGE("Disable Uapsd per ac Failed vdevId %d ac %d", vdev_id,
1217 ac);
Govind Singh09c3b492016-03-08 16:05:14 +05301218 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001219 }
1220 WMA_LOGD("Disable Uapsd per ac vdevId %d val %d", vdev_id,
1221 iface->uapsd_cached_val);
Govind Singh09c3b492016-03-08 16:05:14 +05301222
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301223 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001224}
1225
1226/**
1227 * wma_get_temperature() - get pdev temperature req
1228 * @wmi_handle: wma handle
1229 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301230 * Return: QDF_STATUS_SUCCESS for success or error code.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001231 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301232QDF_STATUS wma_get_temperature(tp_wma_handle wma_handle)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001233{
Govind Singh09c3b492016-03-08 16:05:14 +05301234 QDF_STATUS ret = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001235
Govind Singh09c3b492016-03-08 16:05:14 +05301236 ret = wmi_unified_get_temperature(wma_handle->wmi_handle);
1237 if (ret)
1238 WMA_LOGE("Failed to send set Mimo PS ret = %d", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001239
Govind Singh09c3b492016-03-08 16:05:14 +05301240 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001241}
1242
1243/**
1244 * wma_pdev_temperature_evt_handler() - pdev temperature event handler
1245 * @handle: wma handle
1246 * @event: event buffer
1247 * @len : length
1248 *
1249 * Return: 0 for success or error code.
1250 */
1251int wma_pdev_temperature_evt_handler(void *handle, uint8_t *event,
1252 uint32_t len)
1253{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301254 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001255 cds_msg_t sme_msg = { 0 };
1256 WMI_PDEV_TEMPERATURE_EVENTID_param_tlvs *param_buf;
1257 wmi_pdev_temperature_event_fixed_param *wmi_event;
1258
1259 param_buf = (WMI_PDEV_TEMPERATURE_EVENTID_param_tlvs *) event;
1260 if (!param_buf) {
1261 WMA_LOGE("Invalid pdev_temperature event buffer");
1262 return -EINVAL;
1263 }
1264
1265 wmi_event = param_buf->fixed_param;
1266 WMA_LOGI(FL("temperature: %d"), wmi_event->value);
1267
1268 sme_msg.type = eWNI_SME_MSG_GET_TEMPERATURE_IND;
1269 sme_msg.bodyptr = NULL;
1270 sme_msg.bodyval = wmi_event->value;
1271
Anurag Chouhan6d760662016-02-20 16:05:43 +05301272 qdf_status = cds_mq_post_message(QDF_MODULE_ID_SME, &sme_msg);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301273 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001274 WMA_LOGE(FL("Fail to post get temperature ind msg"));
1275 }
1276
1277 return 0;
1278}
1279
1280/**
1281 * wma_process_tx_power_limits() - sends the power limits for 2g/5g to firmware
1282 * @handle: wma handle
1283 * @ptxlim: power limit value
1284 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301285 * Return: QDF_STATUS_SUCCESS for success or error code.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001286 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301287QDF_STATUS wma_process_tx_power_limits(WMA_HANDLE handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001288 tSirTxPowerLimit *ptxlim)
1289{
1290 tp_wma_handle wma = (tp_wma_handle) handle;
1291 int32_t ret = 0;
1292 uint32_t txpower_params2g = 0;
1293 uint32_t txpower_params5g = 0;
Govind Singhd76a5b02016-03-08 15:12:14 +05301294 struct pdev_params pdevparam;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001295
1296 if (!wma || !wma->wmi_handle) {
1297 WMA_LOGE("%s: WMA is closed, can not issue tx power limit",
1298 __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301299 return QDF_STATUS_E_INVAL;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001300 }
1301 /* Set value and reason code for 2g and 5g power limit */
1302
1303 SET_PDEV_PARAM_TXPOWER_REASON(txpower_params2g,
1304 WMI_PDEV_PARAM_TXPOWER_REASON_SAR);
1305 SET_PDEV_PARAM_TXPOWER_VALUE(txpower_params2g, ptxlim->txPower2g);
1306
1307 SET_PDEV_PARAM_TXPOWER_REASON(txpower_params5g,
1308 WMI_PDEV_PARAM_TXPOWER_REASON_SAR);
1309 SET_PDEV_PARAM_TXPOWER_VALUE(txpower_params5g, ptxlim->txPower5g);
1310
1311 WMA_LOGD("%s: txpower2g: %x txpower5g: %x",
1312 __func__, txpower_params2g, txpower_params5g);
1313
Govind Singhd76a5b02016-03-08 15:12:14 +05301314 pdevparam.param_id = WMI_PDEV_PARAM_TXPOWER_LIMIT2G;
1315 pdevparam.param_value = txpower_params2g;
1316 ret = wmi_unified_pdev_param_send(wma->wmi_handle,
1317 &pdevparam,
1318 WMA_WILDCARD_PDEV_ID);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001319 if (ret) {
1320 WMA_LOGE("%s: Failed to set txpower 2g (%d)", __func__, ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301321 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001322 }
Govind Singhd76a5b02016-03-08 15:12:14 +05301323 pdevparam.param_id = WMI_PDEV_PARAM_TXPOWER_LIMIT5G;
1324 pdevparam.param_value = txpower_params5g;
1325 ret = wmi_unified_pdev_param_send(wma->wmi_handle,
1326 &pdevparam,
1327 WMA_WILDCARD_PDEV_ID);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001328 if (ret) {
1329 WMA_LOGE("%s: Failed to set txpower 5g (%d)", __func__, ret);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301330 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001331 }
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301332 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001333}
1334
1335/**
1336 * wma_add_p2p_ie() - add p2p IE
1337 * @frm: ptr where p2p ie needs to add
1338 *
1339 * Return: ptr after p2p ie
1340 */
1341uint8_t *wma_add_p2p_ie(uint8_t *frm)
1342{
1343 uint8_t wfa_oui[3] = WMA_P2P_WFA_OUI;
1344 struct p2p_ie *p2p_ie = (struct p2p_ie *)frm;
1345
1346 p2p_ie->p2p_id = WMA_P2P_IE_ID;
1347 p2p_ie->p2p_oui[0] = wfa_oui[0];
1348 p2p_ie->p2p_oui[1] = wfa_oui[1];
1349 p2p_ie->p2p_oui[2] = wfa_oui[2];
1350 p2p_ie->p2p_oui_type = WMA_P2P_WFA_VER;
1351 p2p_ie->p2p_len = 4;
1352 return frm + sizeof(struct p2p_ie);
1353}
1354
1355/**
1356 * wma_update_beacon_noa_ie() - update beacon ie
1357 * @bcn: beacon info
1358 * @new_noa_sub_ie_len: ie length
1359 *
1360 * Return: none
1361 */
1362static void wma_update_beacon_noa_ie(struct beacon_info *bcn,
1363 uint16_t new_noa_sub_ie_len)
1364{
1365 struct p2p_ie *p2p_ie;
1366 uint8_t *buf;
1367
1368 /* if there is nothing to add, just return */
1369 if (new_noa_sub_ie_len == 0) {
1370 if (bcn->noa_sub_ie_len && bcn->noa_ie) {
1371 WMA_LOGD("%s: NoA is present in previous beacon, "
1372 "but not present in swba event, "
1373 "So Reset the NoA", __func__);
1374 /* TODO: Assuming p2p noa ie is last ie in the beacon */
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301375 qdf_mem_zero(bcn->noa_ie, (bcn->noa_sub_ie_len +
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001376 sizeof(struct p2p_ie)));
1377 bcn->len -= (bcn->noa_sub_ie_len +
1378 sizeof(struct p2p_ie));
1379 bcn->noa_ie = NULL;
1380 bcn->noa_sub_ie_len = 0;
1381 }
1382 WMA_LOGD("%s: No need to update NoA", __func__);
1383 return;
1384 }
1385
1386 if (bcn->noa_sub_ie_len && bcn->noa_ie) {
1387 /* NoA present in previous beacon, update it */
1388 WMA_LOGD("%s: NoA present in previous beacon, "
1389 "update the NoA IE, bcn->len %u"
1390 "bcn->noa_sub_ie_len %u",
1391 __func__, bcn->len, bcn->noa_sub_ie_len);
1392 bcn->len -= (bcn->noa_sub_ie_len + sizeof(struct p2p_ie));
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301393 qdf_mem_zero(bcn->noa_ie,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001394 (bcn->noa_sub_ie_len + sizeof(struct p2p_ie)));
1395 } else { /* NoA is not present in previous beacon */
1396 WMA_LOGD("%s: NoA not present in previous beacon, add it"
1397 "bcn->len %u", __func__, bcn->len);
Nirav Shahcbc6d722016-03-01 16:24:53 +05301398 buf = qdf_nbuf_data(bcn->buf);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001399 bcn->noa_ie = buf + bcn->len;
1400 }
1401
1402 bcn->noa_sub_ie_len = new_noa_sub_ie_len;
1403 wma_add_p2p_ie(bcn->noa_ie);
1404 p2p_ie = (struct p2p_ie *)bcn->noa_ie;
1405 p2p_ie->p2p_len += new_noa_sub_ie_len;
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301406 qdf_mem_copy((bcn->noa_ie + sizeof(struct p2p_ie)), bcn->noa_sub_ie,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001407 new_noa_sub_ie_len);
1408
1409 bcn->len += (new_noa_sub_ie_len + sizeof(struct p2p_ie));
1410 WMA_LOGI("%s: Updated beacon length with NoA Ie is %u",
1411 __func__, bcn->len);
1412}
1413
1414/**
1415 * wma_p2p_create_sub_ie_noa() - put p2p noa ie
1416 * @buf: buffer
1417 * @noa: noa element ie
1418 * @new_noa_sub_ie_len: ie length
1419 *
1420 * Return: none
1421 */
1422static void wma_p2p_create_sub_ie_noa(uint8_t *buf,
1423 struct p2p_sub_element_noa *noa,
1424 uint16_t *new_noa_sub_ie_len)
1425{
1426 uint8_t tmp_octet = 0;
1427 int i;
1428 uint8_t *buf_start = buf;
1429
1430 *buf++ = WMA_P2P_SUB_ELEMENT_NOA; /* sub-element id */
1431 ASSERT(noa->num_descriptors <= WMA_MAX_NOA_DESCRIPTORS);
1432
1433 /*
1434 * Length = (2 octets for Index and CTWin/Opp PS) and
1435 * (13 octets for each NOA Descriptors)
1436 */
1437 P2PIE_PUT_LE16(buf, WMA_NOA_IE_SIZE(noa->num_descriptors));
1438 buf += 2;
1439
1440 *buf++ = noa->index; /* Instance Index */
1441
1442 tmp_octet = noa->ctwindow & WMA_P2P_NOA_IE_CTWIN_MASK;
1443 if (noa->oppPS) {
1444 tmp_octet |= WMA_P2P_NOA_IE_OPP_PS_SET;
1445 }
1446 *buf++ = tmp_octet; /* Opp Ps and CTWin capabilities */
1447
1448 for (i = 0; i < noa->num_descriptors; i++) {
1449 ASSERT(noa->noa_descriptors[i].type_count != 0);
1450
1451 *buf++ = noa->noa_descriptors[i].type_count;
1452
1453 P2PIE_PUT_LE32(buf, noa->noa_descriptors[i].duration);
1454 buf += 4;
1455 P2PIE_PUT_LE32(buf, noa->noa_descriptors[i].interval);
1456 buf += 4;
1457 P2PIE_PUT_LE32(buf, noa->noa_descriptors[i].start_time);
1458 buf += 4;
1459 }
1460 *new_noa_sub_ie_len = (buf - buf_start);
1461}
1462
1463/**
1464 * wma_update_noa() - update noa params
1465 * @beacon: beacon info
1466 * @noa_ie: noa ie
1467 *
1468 * Return: none
1469 */
1470void wma_update_noa(struct beacon_info *beacon,
1471 struct p2p_sub_element_noa *noa_ie)
1472{
1473 uint16_t new_noa_sub_ie_len;
1474
1475 /* Call this function by holding the spinlock on beacon->lock */
1476
1477 if (noa_ie) {
1478 if ((noa_ie->ctwindow == 0) && (noa_ie->oppPS == 0) &&
1479 (noa_ie->num_descriptors == 0)) {
1480 /* NoA is not present */
1481 WMA_LOGD("%s: NoA is not present", __func__);
1482 new_noa_sub_ie_len = 0;
1483 } else {
1484 /* Create the binary blob containing NOA sub-IE */
1485 WMA_LOGD("%s: Create NOA sub ie", __func__);
1486 wma_p2p_create_sub_ie_noa(&beacon->noa_sub_ie[0],
1487 noa_ie, &new_noa_sub_ie_len);
1488 }
1489 } else {
1490 WMA_LOGD("%s: No need to add NOA", __func__);
1491 new_noa_sub_ie_len = 0; /* no NOA IE sub-attributes */
1492 }
1493
1494 wma_update_beacon_noa_ie(beacon, new_noa_sub_ie_len);
1495}
1496
1497/**
1498 * wma_update_probe_resp_noa() - update noa IE in probe response
1499 * @wma_handle: wma handle
1500 * @noa_ie: noa ie
1501 *
1502 * Return: none
1503 */
1504void wma_update_probe_resp_noa(tp_wma_handle wma_handle,
1505 struct p2p_sub_element_noa *noa_ie)
1506{
1507 tSirP2PNoaAttr *noa_attr =
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301508 (tSirP2PNoaAttr *) qdf_mem_malloc(sizeof(tSirP2PNoaAttr));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001509 WMA_LOGD("Received update NoA event");
1510 if (!noa_attr) {
1511 WMA_LOGE("Failed to allocate memory for tSirP2PNoaAttr");
1512 return;
1513 }
1514
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301515 qdf_mem_zero(noa_attr, sizeof(tSirP2PNoaAttr));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001516
1517 noa_attr->index = noa_ie->index;
1518 noa_attr->oppPsFlag = noa_ie->oppPS;
1519 noa_attr->ctWin = noa_ie->ctwindow;
1520 if (!noa_ie->num_descriptors) {
1521 WMA_LOGD("Zero NoA descriptors");
1522 } else {
1523 WMA_LOGD("%d NoA descriptors", noa_ie->num_descriptors);
1524 noa_attr->uNoa1IntervalCnt =
1525 noa_ie->noa_descriptors[0].type_count;
1526 noa_attr->uNoa1Duration = noa_ie->noa_descriptors[0].duration;
1527 noa_attr->uNoa1Interval = noa_ie->noa_descriptors[0].interval;
1528 noa_attr->uNoa1StartTime =
1529 noa_ie->noa_descriptors[0].start_time;
1530 if (noa_ie->num_descriptors > 1) {
1531 noa_attr->uNoa2IntervalCnt =
1532 noa_ie->noa_descriptors[1].type_count;
1533 noa_attr->uNoa2Duration =
1534 noa_ie->noa_descriptors[1].duration;
1535 noa_attr->uNoa2Interval =
1536 noa_ie->noa_descriptors[1].interval;
1537 noa_attr->uNoa2StartTime =
1538 noa_ie->noa_descriptors[1].start_time;
1539 }
1540 }
1541 WMA_LOGI("Sending SIR_HAL_P2P_NOA_ATTR_IND to LIM");
1542 wma_send_msg(wma_handle, SIR_HAL_P2P_NOA_ATTR_IND, (void *)noa_attr, 0);
1543}
1544
1545/**
1546 * wma_p2p_noa_event_handler() - p2p noa event handler
1547 * @handle: wma handle
1548 * @event: event data
1549 * @len: length
1550 *
1551 * Return: 0 for success or error code.
1552 */
1553int wma_p2p_noa_event_handler(void *handle, uint8_t *event,
1554 uint32_t len)
1555{
1556 tp_wma_handle wma = (tp_wma_handle) handle;
1557 WMI_P2P_NOA_EVENTID_param_tlvs *param_buf;
1558 wmi_p2p_noa_event_fixed_param *p2p_noa_event;
1559 uint8_t vdev_id, i;
1560 wmi_p2p_noa_info *p2p_noa_info;
1561 struct p2p_sub_element_noa noa_ie;
1562 uint8_t *buf_ptr;
1563 uint32_t descriptors;
1564
1565 param_buf = (WMI_P2P_NOA_EVENTID_param_tlvs *) event;
1566 if (!param_buf) {
1567 WMA_LOGE("Invalid P2P NoA event buffer");
1568 return -EINVAL;
1569 }
1570
1571 p2p_noa_event = param_buf->fixed_param;
1572 buf_ptr = (uint8_t *) p2p_noa_event;
1573 buf_ptr += sizeof(wmi_p2p_noa_event_fixed_param);
1574 p2p_noa_info = (wmi_p2p_noa_info *) (buf_ptr);
1575 vdev_id = p2p_noa_event->vdev_id;
1576
1577 if (WMI_UNIFIED_NOA_ATTR_IS_MODIFIED(p2p_noa_info)) {
1578
Anurag Chouhan600c3a02016-03-01 10:33:54 +05301579 qdf_mem_zero(&noa_ie, sizeof(noa_ie));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001580 noa_ie.index =
1581 (uint8_t) WMI_UNIFIED_NOA_ATTR_INDEX_GET(p2p_noa_info);
1582 noa_ie.oppPS =
1583 (uint8_t) WMI_UNIFIED_NOA_ATTR_OPP_PS_GET(p2p_noa_info);
1584 noa_ie.ctwindow =
1585 (uint8_t) WMI_UNIFIED_NOA_ATTR_CTWIN_GET(p2p_noa_info);
1586 descriptors = WMI_UNIFIED_NOA_ATTR_NUM_DESC_GET(p2p_noa_info);
1587 noa_ie.num_descriptors = (uint8_t) descriptors;
1588
1589 WMA_LOGI("%s: index %u, oppPs %u, ctwindow %u, "
1590 "num_descriptors = %u", __func__, noa_ie.index,
1591 noa_ie.oppPS, noa_ie.ctwindow, noa_ie.num_descriptors);
1592 for (i = 0; i < noa_ie.num_descriptors; i++) {
1593 noa_ie.noa_descriptors[i].type_count =
1594 (uint8_t) p2p_noa_info->noa_descriptors[i].
1595 type_count;
1596 noa_ie.noa_descriptors[i].duration =
1597 p2p_noa_info->noa_descriptors[i].duration;
1598 noa_ie.noa_descriptors[i].interval =
1599 p2p_noa_info->noa_descriptors[i].interval;
1600 noa_ie.noa_descriptors[i].start_time =
1601 p2p_noa_info->noa_descriptors[i].start_time;
1602 WMA_LOGI("%s: NoA descriptor[%d] type_count %u, "
1603 "duration %u, interval %u, start_time = %u",
1604 __func__, i,
1605 noa_ie.noa_descriptors[i].type_count,
1606 noa_ie.noa_descriptors[i].duration,
1607 noa_ie.noa_descriptors[i].interval,
1608 noa_ie.noa_descriptors[i].start_time);
1609 }
1610
1611 /* Send a msg to LIM to update the NoA IE in probe response
1612 * frames transmitted by the host */
1613 wma_update_probe_resp_noa(wma, &noa_ie);
1614 }
1615
1616 return 0;
1617}
1618
1619/**
1620 * wma_set_p2pgo_noa_req() - send p2p go noa request to fw
1621 * @wma: wma handle
1622 * @noa: p2p power save parameters
1623 *
1624 * Return: none
1625 */
1626static void wma_set_p2pgo_noa_req(tp_wma_handle wma, tP2pPsParams *noa)
1627{
Govind Singh09c3b492016-03-08 16:05:14 +05301628 QDF_STATUS ret;
1629 struct p2p_ps_params cmd = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001630
Govind Singh09c3b492016-03-08 16:05:14 +05301631 cmd.opp_ps = noa->opp_ps;
1632 cmd.ctwindow = noa->ctWindow;
1633 cmd.count = noa->count;
1634 cmd.duration = noa->duration;
1635 cmd.interval = noa->interval;
1636 cmd.single_noa_duration = noa->single_noa_duration;
1637 cmd.ps_selection = noa->psSelection;
1638 cmd.session_id = noa->sessionId;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001639
Govind Singh09c3b492016-03-08 16:05:14 +05301640 ret = wmi_unified_set_p2pgo_noa_req_cmd(wma->wmi_handle,
1641 &cmd);
1642 if (QDF_IS_STATUS_ERROR(ret))
1643 WMA_LOGE("Failed to send set uapsd param ret = %d", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001644
Govind Singh09c3b492016-03-08 16:05:14 +05301645 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001646}
1647
1648/**
1649 * wma_set_p2pgo_oppps_req() - send p2p go opp power save request to fw
1650 * @wma: wma handle
1651 * @noa: p2p opp power save parameters
1652 *
1653 * Return: none
1654 */
1655static void wma_set_p2pgo_oppps_req(tp_wma_handle wma, tP2pPsParams *oppps)
1656{
Govind Singh09c3b492016-03-08 16:05:14 +05301657 QDF_STATUS ret;
1658 struct p2p_ps_params cmd = {0};
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001659
Govind Singh09c3b492016-03-08 16:05:14 +05301660 cmd.opp_ps = oppps->opp_ps;
1661 cmd.ctwindow = oppps->ctWindow;
1662 cmd.count = oppps->count;
1663 cmd.duration = oppps->duration;
1664 cmd.interval = oppps->interval;
1665 cmd.single_noa_duration = oppps->single_noa_duration;
1666 cmd.ps_selection = oppps->psSelection;
1667 cmd.session_id = oppps->sessionId;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001668
Govind Singh09c3b492016-03-08 16:05:14 +05301669 ret = wmi_unified_set_p2pgo_oppps_req(wma->wmi_handle,
1670 &cmd);
1671 if (QDF_IS_STATUS_ERROR(ret))
1672 WMA_LOGE("Failed to send set uapsd param ret = %d", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001673
Govind Singh09c3b492016-03-08 16:05:14 +05301674 return;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001675}
1676
1677/**
1678 * wma_process_set_p2pgo_noa_req() - process p2pgo noa request
1679 * @handle: wma handle
1680 * @ps_params: powersave params
1681 *
1682 * Return: none
1683 */
1684void wma_process_set_p2pgo_noa_req(tp_wma_handle wma,
1685 tP2pPsParams *ps_params)
1686{
1687 WMA_LOGD("%s: Enter", __func__);
1688 if (ps_params->opp_ps) {
1689 wma_set_p2pgo_oppps_req(wma, ps_params);
1690 } else {
1691 wma_set_p2pgo_noa_req(wma, ps_params);
1692 }
1693
1694 WMA_LOGD("%s: Exit", __func__);
1695}
1696
1697/**
1698 * wma_process_set_mimops_req() - Set the received MiMo PS state to firmware
1699 * @handle: wma handle
1700 * @mimops: MIMO powersave params
1701 *
1702 * Return: none
1703 */
1704void wma_process_set_mimops_req(tp_wma_handle wma_handle,
1705 tSetMIMOPS *mimops)
1706{
1707 /* Translate to what firmware understands */
1708 if (mimops->htMIMOPSState == eSIR_HT_MIMO_PS_DYNAMIC)
1709 mimops->htMIMOPSState = WMI_PEER_MIMO_PS_DYNAMIC;
1710 else if (mimops->htMIMOPSState == eSIR_HT_MIMO_PS_STATIC)
1711 mimops->htMIMOPSState = WMI_PEER_MIMO_PS_STATIC;
1712 else if (mimops->htMIMOPSState == eSIR_HT_MIMO_PS_NO_LIMIT)
1713 mimops->htMIMOPSState = WMI_PEER_MIMO_PS_NONE;
1714
1715 WMA_LOGD("%s: htMIMOPSState = %d, sessionId = %d \
1716 peerMac <%02x:%02x:%02x:%02x:%02x:%02x>", __func__,
1717 mimops->htMIMOPSState, mimops->sessionId, mimops->peerMac[0],
1718 mimops->peerMac[1], mimops->peerMac[2], mimops->peerMac[3],
1719 mimops->peerMac[4], mimops->peerMac[5]);
1720
1721 wma_set_peer_param(wma_handle, mimops->peerMac,
1722 WMI_PEER_MIMO_PS_STATE, mimops->htMIMOPSState,
1723 mimops->sessionId);
1724}
1725
1726/**
1727 * wma_set_mimops() - set MIMO powersave
1728 * @handle: wma handle
1729 * @vdev_id: vdev id
1730 * @value: value
1731 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301732 * Return: QDF_STATUS_SUCCESS for success or error code.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001733 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301734QDF_STATUS wma_set_mimops(tp_wma_handle wma, uint8_t vdev_id, int value)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001735{
Govind Singh09c3b492016-03-08 16:05:14 +05301736 QDF_STATUS ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001737
Govind Singh09c3b492016-03-08 16:05:14 +05301738 ret = wmi_unified_set_mimops(wma->wmi_handle, vdev_id,
1739 value);
1740 if (QDF_IS_STATUS_ERROR(ret))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001741 WMA_LOGE("Failed to send set Mimo PS ret = %d", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001742
1743 return ret;
1744}
1745
1746/**
1747 * wma_notify_modem_power_state() - notify modem power state
1748 * @wma_ptr: wma handle
1749 * @pReq: modem power state
1750 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301751 * Return: QDF_STATUS_SUCCESS for success or error code.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001752 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301753QDF_STATUS wma_notify_modem_power_state(void *wma_ptr,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001754 tSirModemPowerStateInd *pReq)
1755{
1756 int32_t ret;
1757 tp_wma_handle wma = (tp_wma_handle) wma_ptr;
1758
1759 WMA_LOGD("%s: WMA notify Modem Power State %d", __func__, pReq->param);
1760
Govind Singhd76a5b02016-03-08 15:12:14 +05301761 ret = wma_unified_modem_power_state(wma->wmi_handle, pReq->param);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001762 if (ret) {
1763 WMA_LOGE("%s: Fail to notify Modem Power State %d",
1764 __func__, pReq->param);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301765 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001766 }
1767
1768 WMA_LOGD("Successfully notify Modem Power State %d", pReq->param);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301769 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001770}
1771
1772/**
1773 * wma_set_idle_ps_config() - enable/disble Low Power Support(Pdev Specific)
1774 * @wma_ptr: wma handle
1775 * @idle_ps: idle powersave
1776 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301777 * Return: QDF_STATUS_SUCCESS for success or error code.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001778 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301779QDF_STATUS wma_set_idle_ps_config(void *wma_ptr, uint32_t idle_ps)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001780{
1781 int32_t ret;
1782 tp_wma_handle wma = (tp_wma_handle) wma_ptr;
Govind Singhd76a5b02016-03-08 15:12:14 +05301783 struct pdev_params pdevparam;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001784
1785 WMA_LOGD("WMA Set Idle Ps Config [1:set 0:clear] val %d", idle_ps);
1786
1787 /* Set Idle Mode Power Save Config */
Govind Singhd76a5b02016-03-08 15:12:14 +05301788 pdevparam.param_id = WMI_PDEV_PARAM_IDLE_PS_CONFIG;
1789 pdevparam.param_value = idle_ps;
1790 ret = wmi_unified_pdev_param_send(wma->wmi_handle,
1791 &pdevparam,
1792 WMA_WILDCARD_PDEV_ID);
1793
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001794 if (ret) {
1795 WMA_LOGE("Fail to Set Idle Ps Config %d", idle_ps);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301796 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001797 }
1798
1799 WMA_LOGD("Successfully Set Idle Ps Config %d", idle_ps);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301800 return QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001801}
1802
1803/**
1804 * wma_set_smps_params() - set smps params
1805 * @wma: wma handle
1806 * @vdev_id: vdev id
1807 * @value: value
1808 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301809 * Return: QDF_STATUS_SUCCESS for success or error code.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001810 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05301811QDF_STATUS wma_set_smps_params(tp_wma_handle wma, uint8_t vdev_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001812 int value)
1813{
Govind Singh09c3b492016-03-08 16:05:14 +05301814 QDF_STATUS ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001815
Govind Singh09c3b492016-03-08 16:05:14 +05301816 ret = wmi_unified_set_smps_params(wma->wmi_handle, vdev_id,
1817 value);
1818 if (QDF_IS_STATUS_ERROR(ret))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001819 WMA_LOGE("Failed to send set Mimo PS ret = %d", ret);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001820
1821 return ret;
1822}
1823
1824/**
1825 * wma_set_vdev_suspend_dtim() - set suspend dtim parameters in fw
1826 * @wma: wma handle
1827 * @vdev_id: vdev id
1828 *
1829 * Return: none
1830 */
1831static void wma_set_vdev_suspend_dtim(tp_wma_handle wma, uint8_t vdev_id)
1832{
1833 struct wma_txrx_node *iface = &wma->interfaces[vdev_id];
1834 enum powersave_qpower_mode qpower_config = wma_get_qpower_config(wma);
1835
1836 if ((iface->type == WMI_VDEV_TYPE_STA) &&
1837 (iface->ps_enabled == true) &&
1838 (iface->dtimPeriod != 0)) {
Govind Singhd76a5b02016-03-08 15:12:14 +05301839 QDF_STATUS ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001840 uint32_t listen_interval;
1841 uint32_t max_mod_dtim;
1842
1843 if (wma->staDynamicDtim) {
1844 listen_interval = wma->staDynamicDtim;
1845 } else if ((wma->staModDtim) &&
1846 (wma->staMaxLIModDtim)) {
1847 /*
1848 * When the system is in suspend
1849 * (maximum beacon will be at 1s == 10)
1850 * If maxModulatedDTIM ((MAX_LI_VAL = 10) / AP_DTIM)
1851 * equal or larger than MDTIM
1852 * (configured in WCNSS_qcom_cfg.ini)
1853 * Set LI to MDTIM * AP_DTIM
1854 * If Dtim = 2 and Mdtim = 2 then LI is 4
1855 * Else
1856 * Set LI to maxModulatedDTIM * AP_DTIM
1857 */
1858 max_mod_dtim = wma->staMaxLIModDtim / iface->dtimPeriod;
1859 if (max_mod_dtim >= wma->staModDtim) {
1860 listen_interval =
1861 (wma->staModDtim * iface->dtimPeriod);
1862 } else {
1863 listen_interval =
1864 (max_mod_dtim * iface->dtimPeriod);
1865 }
1866 } else {
1867 return;
1868 }
1869
Govind Singhd76a5b02016-03-08 15:12:14 +05301870 ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001871 WMI_VDEV_PARAM_LISTEN_INTERVAL,
1872 listen_interval);
Govind Singhd76a5b02016-03-08 15:12:14 +05301873 if (QDF_IS_STATUS_ERROR(ret)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001874 /* Even it fails continue Fw will take default LI */
1875 WMA_LOGE("Failed to Set Listen Interval vdevId %d",
1876 vdev_id);
1877 }
1878
1879 WMA_LOGD("Set Listen Interval vdevId %d Listen Intv %d",
1880 vdev_id, listen_interval);
1881
1882 if (qpower_config) {
1883 WMA_LOGD("disable Qpower in suspend mode!");
Govind Singhd76a5b02016-03-08 15:12:14 +05301884 ret = wma_unified_set_sta_ps_param(wma->wmi_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001885 vdev_id,
1886 WMI_STA_PS_ENABLE_QPOWER,
1887 0);
Govind Singhd76a5b02016-03-08 15:12:14 +05301888 if (QDF_IS_STATUS_ERROR(ret))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001889 WMA_LOGE("Failed to disable Qpower in suspend mode!");
1890
1891 iface->ps_enabled = true;
1892 }
1893
Govind Singhd76a5b02016-03-08 15:12:14 +05301894 ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001895 WMI_VDEV_PARAM_DTIM_POLICY,
1896 NORMAL_DTIM);
Govind Singhd76a5b02016-03-08 15:12:14 +05301897 if (QDF_IS_STATUS_ERROR(ret))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001898 WMA_LOGE("Failed to Set to Normal DTIM vdevId %d",
1899 vdev_id);
1900
1901 /* Set it to Normal DTIM */
1902 iface->dtim_policy = NORMAL_DTIM;
1903 WMA_LOGD("Set DTIM Policy to Normal Dtim vdevId %d", vdev_id);
1904 }
1905}
1906
1907/**
1908 * wma_set_suspend_dtim() - set suspend dtim
1909 * @wma: wma handle
1910 *
1911 * Return: none
1912 */
1913void wma_set_suspend_dtim(tp_wma_handle wma)
1914{
1915 uint8_t i;
1916
1917 if (NULL == wma) {
1918 WMA_LOGE("%s: wma is NULL", __func__);
1919 return;
1920 }
1921
1922 for (i = 0; i < wma->max_bssid; i++) {
1923 if ((wma->interfaces[i].handle) &&
1924 (false == wma->interfaces[i].alt_modulated_dtim_enabled)) {
1925 wma_set_vdev_suspend_dtim(wma, i);
1926 }
1927 }
1928}
1929
1930/**
1931 * wma_set_vdev_resume_dtim() - set resume dtim parameters in fw
1932 * @wma: wma handle
1933 * @vdev_id: vdev id
1934 *
1935 * Return: none
1936 */
1937static void wma_set_vdev_resume_dtim(tp_wma_handle wma, uint8_t vdev_id)
1938{
1939 struct wma_txrx_node *iface = &wma->interfaces[vdev_id];
1940 enum powersave_qpower_mode qpower_config = wma_get_qpower_config(wma);
1941
1942 if ((iface->type == WMI_VDEV_TYPE_STA) &&
1943 (iface->ps_enabled == true) &&
1944 (iface->dtim_policy == NORMAL_DTIM)) {
Govind Singhd76a5b02016-03-08 15:12:14 +05301945 QDF_STATUS ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001946 uint32_t cfg_data_val = 0;
1947 /* get mac to acess CFG data base */
Anurag Chouhan6d760662016-02-20 16:05:43 +05301948 struct sAniSirGlobal *mac = cds_get_context(QDF_MODULE_ID_PE);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001949 /* Set Listen Interval */
1950 if ((NULL == mac) || (wlan_cfg_get_int(mac,
1951 WNI_CFG_LISTEN_INTERVAL,
1952 &cfg_data_val) !=
1953 eSIR_SUCCESS)) {
Anurag Chouhanb2dc16f2016-02-25 11:47:37 +05301954 QDF_TRACE(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_ERROR,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001955 "Failed to get value for listen interval");
1956 cfg_data_val = POWERSAVE_DEFAULT_LISTEN_INTERVAL;
1957 }
1958
Govind Singhd76a5b02016-03-08 15:12:14 +05301959 ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001960 WMI_VDEV_PARAM_LISTEN_INTERVAL,
1961 cfg_data_val);
Govind Singhd76a5b02016-03-08 15:12:14 +05301962 if (QDF_IS_STATUS_ERROR(ret)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001963 /* Even it fails continue Fw will take default LI */
1964 WMA_LOGE("Failed to Set Listen Interval vdevId %d",
1965 vdev_id);
1966 }
1967
1968 WMA_LOGD("Set Listen Interval vdevId %d Listen Intv %d",
1969 vdev_id, cfg_data_val);
1970
Govind Singhd76a5b02016-03-08 15:12:14 +05301971 ret = wma_vdev_set_param(wma->wmi_handle, vdev_id,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001972 WMI_VDEV_PARAM_DTIM_POLICY,
1973 STICK_DTIM);
Govind Singhd76a5b02016-03-08 15:12:14 +05301974 if (QDF_IS_STATUS_ERROR(ret)) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001975 /* Set it back to Stick DTIM */
1976 WMA_LOGE("Failed to Set to Stick DTIM vdevId %d",
1977 vdev_id);
1978 }
1979 iface->dtim_policy = STICK_DTIM;
1980 WMA_LOGD("Set DTIM Policy to Stick Dtim vdevId %d", vdev_id);
1981
1982 if (qpower_config) {
1983 WMA_LOGD("enable Qpower in resume mode!");
Govind Singhd76a5b02016-03-08 15:12:14 +05301984 ret = wma_unified_set_sta_ps_param(wma->wmi_handle,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001985 vdev_id,
1986 WMI_STA_PS_ENABLE_QPOWER,
1987 1);
Govind Singhd76a5b02016-03-08 15:12:14 +05301988 if (QDF_IS_STATUS_ERROR(ret))
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001989 WMA_LOGE("Failed to enable Qpower in resume mode!");
1990 }
1991 }
1992}
1993
1994/**
1995 * wma_set_resume_dtim() - set resume dtim
1996 * @wma: wma handle
1997 *
1998 * Return: none
1999 */
2000void wma_set_resume_dtim(tp_wma_handle wma)
2001{
2002 uint8_t i;
2003
2004 if (NULL == wma) {
2005 WMA_LOGE("%s: wma is NULL", __func__);
2006 return;
2007 }
2008
2009 for (i = 0; i < wma->max_bssid; i++) {
2010 if ((wma->interfaces[i].handle) &&
2011 (false == wma->interfaces[i].alt_modulated_dtim_enabled)) {
2012 wma_set_vdev_resume_dtim(wma, i);
2013 }
2014 }
2015}
2016
Peng Xu4d67c8f2015-10-16 16:02:26 -07002017/**
2018 * wma_set_tx_power_scale() - set tx power scale
2019 * @vdev_id: vdev id
2020 * @value: value
2021 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302022 * Return: QDF_STATUS_SUCCESS for success or error code.
Peng Xu4d67c8f2015-10-16 16:02:26 -07002023 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302024QDF_STATUS wma_set_tx_power_scale(uint8_t vdev_id, int value)
Peng Xu4d67c8f2015-10-16 16:02:26 -07002025{
Govind Singhd76a5b02016-03-08 15:12:14 +05302026 QDF_STATUS ret = QDF_STATUS_SUCCESS;
Peng Xu4d67c8f2015-10-16 16:02:26 -07002027 tp_wma_handle wma_handle =
Anurag Chouhan6d760662016-02-20 16:05:43 +05302028 (tp_wma_handle)cds_get_context(QDF_MODULE_ID_WMA);
Govind Singhd76a5b02016-03-08 15:12:14 +05302029
Peng Xu4d67c8f2015-10-16 16:02:26 -07002030 if (NULL == wma_handle) {
2031 WMA_LOGE("%s: wma_handle is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302032 return QDF_STATUS_E_FAILURE;
Peng Xu4d67c8f2015-10-16 16:02:26 -07002033 }
2034
2035 if (!(wma_handle->interfaces[vdev_id].vdev_up)) {
2036 WMA_LOGE("%s: vdev id %d is not up", __func__, vdev_id);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302037 return QDF_STATUS_E_FAILURE;
Peng Xu4d67c8f2015-10-16 16:02:26 -07002038 }
2039
Govind Singhd76a5b02016-03-08 15:12:14 +05302040 ret = wma_vdev_set_param(wma_handle->wmi_handle, vdev_id,
Peng Xu4d67c8f2015-10-16 16:02:26 -07002041 WMI_VDEV_PARAM_TXPOWER_SCALE, value);
Govind Singhd76a5b02016-03-08 15:12:14 +05302042 if (QDF_IS_STATUS_ERROR(ret))
Peng Xu4d67c8f2015-10-16 16:02:26 -07002043 WMA_LOGE("Set tx power scale failed");
2044
2045 return ret;
2046}
2047
2048/**
2049 * wma_set_tx_power_scale_decr_db() - decrease power by DB value
2050 * @vdev_id: vdev id
2051 * @value: value
2052 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302053 * Return: QDF_STATUS_SUCCESS for success or error code.
Peng Xu4d67c8f2015-10-16 16:02:26 -07002054 */
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302055QDF_STATUS wma_set_tx_power_scale_decr_db(uint8_t vdev_id, int value)
Peng Xu4d67c8f2015-10-16 16:02:26 -07002056{
Govind Singhd76a5b02016-03-08 15:12:14 +05302057 QDF_STATUS ret = QDF_STATUS_SUCCESS;
Peng Xu4d67c8f2015-10-16 16:02:26 -07002058 tp_wma_handle wma_handle =
Anurag Chouhan6d760662016-02-20 16:05:43 +05302059 (tp_wma_handle)cds_get_context(QDF_MODULE_ID_WMA);
Govind Singhd76a5b02016-03-08 15:12:14 +05302060
Peng Xu4d67c8f2015-10-16 16:02:26 -07002061 if (NULL == wma_handle) {
2062 WMA_LOGE("%s: wma_handle is NULL", __func__);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302063 return QDF_STATUS_E_FAILURE;
Peng Xu4d67c8f2015-10-16 16:02:26 -07002064 }
2065
2066 if (!(wma_handle->interfaces[vdev_id].vdev_up)) {
2067 WMA_LOGE("%s: vdev id %d is not up", __func__, vdev_id);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +05302068 return QDF_STATUS_E_FAILURE;
Peng Xu4d67c8f2015-10-16 16:02:26 -07002069 }
2070
Govind Singhd76a5b02016-03-08 15:12:14 +05302071 ret = wma_vdev_set_param(wma_handle->wmi_handle, vdev_id,
Peng Xu4d67c8f2015-10-16 16:02:26 -07002072 WMI_VDEV_PARAM_TXPOWER_SCALE_DECR_DB, value);
Govind Singhd76a5b02016-03-08 15:12:14 +05302073 if (QDF_IS_STATUS_ERROR(ret))
Peng Xu4d67c8f2015-10-16 16:02:26 -07002074 WMA_LOGE("Decrease tx power value failed");
2075
2076 return ret;
2077}