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