1 /* 2 * Copyright (c) 2013-2021 The Linux Foundation. All rights reserved. 3 * Copyright (c) 2022-2023 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 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 */ 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 */ 139 QDF_STATUS wma_set_ap_peer_uapsd(tp_wma_handle wma, uint32_t vdev_id, 140 uint8_t *peer_addr, uint8_t uapsd_value, 141 uint8_t max_sp) 142 { 143 uint32_t uapsd = 0; 144 uint32_t max_sp_len = 0; 145 QDF_STATUS ret; 146 struct ap_ps_params param = {0}; 147 148 if (uapsd_value & UAPSD_VO_ENABLED) { 149 uapsd |= WMI_AP_PS_UAPSD_AC3_DELIVERY_EN | 150 WMI_AP_PS_UAPSD_AC3_TRIGGER_EN; 151 } 152 153 if (uapsd_value & UAPSD_VI_ENABLED) { 154 uapsd |= WMI_AP_PS_UAPSD_AC2_DELIVERY_EN | 155 WMI_AP_PS_UAPSD_AC2_TRIGGER_EN; 156 } 157 158 if (uapsd_value & UAPSD_BK_ENABLED) { 159 uapsd |= WMI_AP_PS_UAPSD_AC1_DELIVERY_EN | 160 WMI_AP_PS_UAPSD_AC1_TRIGGER_EN; 161 } 162 163 if (uapsd_value & UAPSD_BE_ENABLED) { 164 uapsd |= WMI_AP_PS_UAPSD_AC0_DELIVERY_EN | 165 WMI_AP_PS_UAPSD_AC0_TRIGGER_EN; 166 } 167 168 switch (max_sp) { 169 case UAPSD_MAX_SP_LEN_2: 170 max_sp_len = WMI_AP_PS_PEER_PARAM_MAX_SP_2; 171 break; 172 case UAPSD_MAX_SP_LEN_4: 173 max_sp_len = WMI_AP_PS_PEER_PARAM_MAX_SP_4; 174 break; 175 case UAPSD_MAX_SP_LEN_6: 176 max_sp_len = WMI_AP_PS_PEER_PARAM_MAX_SP_6; 177 break; 178 default: 179 max_sp_len = WMI_AP_PS_PEER_PARAM_MAX_SP_UNLIMITED; 180 break; 181 } 182 183 wma_debug("Set WMI_AP_PS_PEER_PARAM_UAPSD 0x%x for "QDF_MAC_ADDR_FMT, 184 uapsd, QDF_MAC_ADDR_REF(peer_addr)); 185 param.vdev_id = vdev_id; 186 param.param = WMI_AP_PS_PEER_PARAM_UAPSD; 187 param.value = uapsd; 188 ret = wmi_unified_ap_ps_cmd_send(wma->wmi_handle, peer_addr, 189 ¶m); 190 if (QDF_IS_STATUS_ERROR(ret)) { 191 wma_err("Failed to set WMI_AP_PS_PEER_PARAM_UAPSD for "QDF_MAC_ADDR_FMT, 192 QDF_MAC_ADDR_REF(peer_addr)); 193 return ret; 194 } 195 196 wma_debug("Set WMI_AP_PS_PEER_PARAM_MAX_SP 0x%x for "QDF_MAC_ADDR_FMT, 197 max_sp_len, QDF_MAC_ADDR_REF(peer_addr)); 198 199 param.vdev_id = vdev_id; 200 param.param = WMI_AP_PS_PEER_PARAM_MAX_SP; 201 param.value = max_sp_len; 202 ret = wmi_unified_ap_ps_cmd_send(wma->wmi_handle, peer_addr, 203 ¶m); 204 if (QDF_IS_STATUS_ERROR(ret)) { 205 wma_err("Failed to set WMI_AP_PS_PEER_PARAM_MAX_SP for "QDF_MAC_ADDR_FMT, 206 QDF_MAC_ADDR_REF(peer_addr)); 207 return ret; 208 } 209 210 return QDF_STATUS_SUCCESS; 211 } 212 213 /** 214 * wma_update_edca_params_for_ac() - to update per ac EDCA parameters 215 * @edca_param: EDCA parameters 216 * @wmm_param: wmm parameters 217 * @ac: access category 218 * 219 * Return: none 220 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 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 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 */ 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 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 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 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 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 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 */ 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 */ 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 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 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 1482 static inline uint8_t *wma_add_p2p_ie(uint8_t *frm) 1483 { 1484 return 0; 1485 } 1486 1487 static inline void 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 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 1500 void wma_update_noa(struct beacon_info *beacon, 1501 struct p2p_sub_element_noa *noa_ie) 1502 { 1503 } 1504 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 #endif /* FEATURE_TX_POWER */ 1700 1701