1 /* 2 * Copyright (c) 2017-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 * DOC: target_if_pmo_static.c 21 * 22 * Target interface file for pmo component to 23 * send suspend / resume related cmd and process event. 24 */ 25 26 #include "wma.h" 27 #include "target_if.h" 28 #include "target_if_pmo.h" 29 #include "wmi_unified_api.h" 30 #include "qdf_types.h" 31 #include "pld_common.h" 32 #include <cds_api.h> 33 #include <cdp_txrx_cmn.h> 34 35 #define TGT_WILDCARD_PDEV_ID 0x0 36 37 QDF_STATUS target_if_pmo_send_vdev_update_param_req( 38 struct wlan_objmgr_vdev *vdev, 39 uint32_t param_id, uint32_t param_value) 40 { 41 uint8_t vdev_id; 42 struct wlan_objmgr_psoc *psoc; 43 struct vdev_set_params param = {0}; 44 wmi_unified_t wmi_handle; 45 46 if (!vdev) { 47 target_if_err("vdev ptr passed is NULL"); 48 return QDF_STATUS_E_INVAL; 49 } 50 51 psoc = wlan_vdev_get_psoc(vdev); 52 vdev_id = wlan_vdev_get_id(vdev); 53 if (!psoc) { 54 target_if_err("psoc handle is NULL"); 55 return QDF_STATUS_E_INVAL; 56 } 57 58 /* Any new param_id added here please also add it to 59 * wmi_tag_vdev_set_cmd to be tagged for runtime PM feature 60 * so that it will not invoke runtime PM "get" which will 61 * result resume right after suspend (WOW_ENABLE). 62 */ 63 64 switch (param_id) { 65 case pmo_vdev_param_listen_interval: 66 param_id = wmi_vdev_param_listen_interval; 67 break; 68 case pmo_vdev_param_dtim_policy: 69 param_id = wmi_vdev_param_dtim_policy; 70 break; 71 case pmo_vdev_param_forced_dtim_count: 72 param_id = wmi_vdev_param_force_dtim_cnt; 73 break; 74 case pmo_vdev_param_moddtim: 75 param_id = wmi_vdev_param_moddtim_cnt; 76 break; 77 default: 78 target_if_err("invalid vdev param id %d", param_id); 79 return QDF_STATUS_E_INVAL; 80 } 81 82 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 83 if (!wmi_handle) { 84 target_if_err("Invalid wmi handle"); 85 return QDF_STATUS_E_INVAL; 86 } 87 88 param.vdev_id = vdev_id; 89 param.param_id = param_id; 90 param.param_value = param_value; 91 target_if_debug("set vdev param vdev_id: %d value: %d for param_id: %d", 92 vdev_id, param_value, param_id); 93 return wmi_unified_vdev_set_param_send(wmi_handle, ¶m); 94 } 95 96 #ifdef WLAN_FEATURE_IGMP_OFFLOAD 97 QDF_STATUS target_if_pmo_send_igmp_offload_req( 98 struct wlan_objmgr_vdev *vdev, 99 struct pmo_igmp_offload_req *pmo_igmp_req) 100 { 101 struct wlan_objmgr_psoc *psoc; 102 wmi_unified_t wmi_handle; 103 104 if (!vdev) { 105 target_if_err("vdev ptr passed is NULL"); 106 return QDF_STATUS_E_INVAL; 107 } 108 109 psoc = wlan_vdev_get_psoc(vdev); 110 if (!psoc) { 111 target_if_err("psoc handle is NULL"); 112 return QDF_STATUS_E_INVAL; 113 } 114 115 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 116 if (!wmi_handle) { 117 target_if_err("Invalid wmi handle"); 118 return QDF_STATUS_E_INVAL; 119 } 120 121 return wmi_unified_send_igmp_offload_cmd(wmi_handle, 122 pmo_igmp_req); 123 } 124 #endif 125 126 QDF_STATUS target_if_pmo_send_vdev_ps_param_req( 127 struct wlan_objmgr_vdev *vdev, 128 uint32_t param_id, 129 uint32_t param_value) 130 { 131 uint8_t vdev_id; 132 struct wlan_objmgr_psoc *psoc; 133 QDF_STATUS status; 134 struct sta_ps_params sta_ps_param = {0}; 135 wmi_unified_t wmi_handle; 136 137 if (!vdev) { 138 target_if_err("vdev ptr passed is NULL"); 139 return QDF_STATUS_E_INVAL; 140 } 141 142 psoc = wlan_vdev_get_psoc(vdev); 143 vdev_id = wlan_vdev_get_id(vdev); 144 if (!psoc) { 145 target_if_err("psoc handle is NULL"); 146 return QDF_STATUS_E_INVAL; 147 } 148 149 /* 150 * Any new param_id added here must be added to 151 * wmi_tag_sta_powersave_cmd() to be tagged for runtime PM feature 152 * so that it will not invoke runtime PM "get" which will 153 * result resume right after suspend (WOW_ENABLE). 154 */ 155 switch (param_id) { 156 case pmo_sta_ps_enable_advanced_power: 157 param_id = WMI_STA_PS_ENABLE_OPM; 158 break; 159 case pmo_sta_ps_param_inactivity_time: 160 param_id = WMI_STA_PS_PARAM_INACTIVITY_TIME; 161 break; 162 case pmo_sta_ps_param_ito_repeat_count: 163 param_id = WMI_STA_PS_PARAM_MAX_RESET_ITO_COUNT_ON_TIM_NO_TXRX; 164 break; 165 case pmo_sta_ps_param_spec_wake_interval: 166 param_id = WMI_STA_PS_PARAM_SPEC_WAKE_INTERVAL; 167 break; 168 default: 169 target_if_err("invalid vdev param id %d", param_id); 170 return QDF_STATUS_E_INVAL; 171 } 172 173 sta_ps_param.vdev_id = vdev_id; 174 sta_ps_param.param_id = param_id; 175 sta_ps_param.value = param_value; 176 target_if_debug("set vdev param vdev_id: %d value: %d for param_id: %d", 177 vdev_id, param_value, param_id); 178 179 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 180 if (!wmi_handle) { 181 target_if_err("Invalid wmi handle"); 182 return QDF_STATUS_E_INVAL; 183 } 184 185 status = wmi_unified_sta_ps_cmd_send(wmi_handle, &sta_ps_param); 186 if (QDF_IS_STATUS_ERROR(status)) 187 return status; 188 189 return status; 190 } 191 192 void target_if_pmo_psoc_update_bus_suspend(struct wlan_objmgr_psoc *psoc, 193 uint8_t value) 194 { 195 wmi_unified_t wmi_handle; 196 197 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 198 if (!wmi_handle) { 199 target_if_err("Invalid wmi handle"); 200 return; 201 } 202 203 wmi_set_is_wow_bus_suspended(wmi_handle, value); 204 } 205 206 int target_if_pmo_psoc_get_host_credits(struct wlan_objmgr_psoc *psoc) 207 { 208 wmi_unified_t wmi_handle; 209 210 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 211 if (!wmi_handle) { 212 target_if_err("Invalid wmi handle"); 213 return 0; 214 } 215 216 return wmi_get_host_credits(wmi_handle); 217 } 218 219 int target_if_pmo_psoc_get_pending_cmnds(struct wlan_objmgr_psoc *psoc) 220 { 221 wmi_unified_t wmi_handle; 222 223 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 224 if (!wmi_handle) { 225 target_if_err("Invalid wmi handle"); 226 return 0; 227 } 228 229 return wmi_get_pending_cmds(wmi_handle); 230 } 231 232 void target_if_pmo_update_target_suspend_flag(struct wlan_objmgr_psoc *psoc, 233 uint8_t value) 234 { 235 wmi_unified_t wmi_handle; 236 237 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 238 if (!wmi_handle) { 239 target_if_err("Invalid wmi handle"); 240 return; 241 } 242 243 wmi_set_target_suspend(wmi_handle, value); 244 } 245 246 void target_if_pmo_update_target_suspend_acked_flag( 247 struct wlan_objmgr_psoc *psoc, 248 uint8_t value) 249 { 250 wmi_unified_t wmi_handle; 251 252 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 253 if (!wmi_handle) { 254 target_if_err("Invalid wmi handle"); 255 return; 256 } 257 258 wmi_set_target_suspend_acked(wmi_handle, value); 259 } 260 261 bool target_if_pmo_is_target_suspended(struct wlan_objmgr_psoc *psoc) 262 { 263 wmi_unified_t wmi_handle; 264 265 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 266 if (!wmi_handle) { 267 target_if_err("Invalid wmi handle"); 268 return false; 269 } 270 271 return wmi_is_target_suspended(wmi_handle); 272 } 273 274 QDF_STATUS target_if_pmo_psoc_send_wow_enable_req( 275 struct wlan_objmgr_psoc *psoc, 276 struct pmo_wow_cmd_params *param) 277 { 278 wmi_unified_t wmi_handle; 279 280 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 281 if (!wmi_handle) { 282 target_if_err("Invalid wmi handle"); 283 return QDF_STATUS_E_INVAL; 284 } 285 286 wma_check_and_set_wake_timer(INSTALL_KEY_TIMEOUT_MS); 287 return wmi_unified_wow_enable_send(wmi_handle, 288 (struct wow_cmd_params *)param, 289 TGT_WILDCARD_PDEV_ID); 290 } 291 292 QDF_STATUS target_if_pmo_psoc_send_suspend_req( 293 struct wlan_objmgr_psoc *psoc, 294 struct pmo_suspend_params *param) 295 { 296 wmi_unified_t wmi_handle; 297 298 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 299 if (!wmi_handle) { 300 target_if_err("Invalid wmi handle"); 301 return QDF_STATUS_E_INVAL; 302 } 303 304 return wmi_unified_suspend_send(wmi_handle, 305 (struct suspend_params *) param, 306 TGT_WILDCARD_PDEV_ID); 307 } 308 309 void target_if_pmo_set_runtime_pm_in_progress(struct wlan_objmgr_psoc *psoc, 310 bool value) 311 { 312 wmi_unified_t wmi_handle; 313 314 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 315 if (!wmi_handle) { 316 target_if_err("Invalid wmi handle"); 317 return; 318 } 319 320 return wmi_set_runtime_pm_inprogress(wmi_handle, value); 321 } 322 323 bool target_if_pmo_get_runtime_pm_in_progress( 324 struct wlan_objmgr_psoc *psoc) 325 { 326 wmi_unified_t wmi_handle; 327 328 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 329 if (!wmi_handle) { 330 target_if_err("Invalid wmi handle"); 331 return false; 332 } 333 334 return wmi_get_runtime_pm_inprogress(wmi_handle); 335 } 336 337 #ifdef HOST_WAKEUP_OVER_QMI 338 QDF_STATUS target_if_pmo_psoc_send_host_wakeup_ind( 339 struct wlan_objmgr_psoc *psoc) 340 { 341 qdf_device_t qdf_dev; 342 int ret; 343 344 qdf_dev = wlan_psoc_get_qdf_dev(psoc); 345 if (!qdf_dev) 346 return QDF_STATUS_E_INVAL; 347 348 ret = pld_exit_power_save(qdf_dev->dev); 349 if (ret) { 350 target_if_err("Failed to exit power save, ret: %d", ret); 351 return qdf_status_from_os_return(ret); 352 } 353 354 return QDF_STATUS_SUCCESS; 355 } 356 #else 357 QDF_STATUS target_if_pmo_psoc_send_host_wakeup_ind( 358 struct wlan_objmgr_psoc *psoc) 359 { 360 wmi_unified_t wmi_handle; 361 bool tx_pending_ind = false; 362 363 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 364 if (!wmi_handle) { 365 target_if_err("Invalid wmi handle"); 366 return QDF_STATUS_E_INVAL; 367 } 368 369 if (cdp_get_tx_inqueue(cds_get_context(QDF_MODULE_ID_SOC))) 370 tx_pending_ind = true; 371 372 return wmi_unified_host_wakeup_ind_to_fw_cmd(wmi_handle, 373 tx_pending_ind); 374 } 375 #endif 376 377 QDF_STATUS target_if_pmo_psoc_send_target_resume_req( 378 struct wlan_objmgr_psoc *psoc) 379 { 380 wmi_unified_t wmi_handle; 381 382 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 383 if (!wmi_handle) { 384 target_if_err("Invalid wmi handle"); 385 return QDF_STATUS_E_INVAL; 386 } 387 388 return wmi_unified_resume_send(wmi_handle, TGT_WILDCARD_PDEV_ID); 389 } 390 391 QDF_STATUS 392 target_if_pmo_psoc_send_idle_monitor_cmd(struct wlan_objmgr_psoc *psoc, 393 uint8_t val) 394 { 395 wmi_unified_t wmi_handle; 396 397 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 398 if (!wmi_handle) { 399 target_if_err("Invalid wmi handle"); 400 return QDF_STATUS_E_INVAL; 401 } 402 403 return wmi_unified_send_idle_trigger_monitor(wmi_handle, val); 404 } 405 406 #ifdef FEATURE_WLAN_D0WOW 407 QDF_STATUS target_if_pmo_psoc_send_d0wow_enable_req( 408 struct wlan_objmgr_psoc *psoc) 409 { 410 wmi_unified_t wmi_handle; 411 412 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 413 if (!wmi_handle) { 414 target_if_err("Invalid wmi handle"); 415 return QDF_STATUS_E_INVAL; 416 } 417 418 return wmi_unified_d0wow_enable_send(wmi_handle, TGT_WILDCARD_PDEV_ID); 419 } 420 421 QDF_STATUS target_if_pmo_psoc_send_d0wow_disable_req( 422 struct wlan_objmgr_psoc *psoc) 423 { 424 wmi_unified_t wmi_handle; 425 426 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 427 if (!wmi_handle) { 428 target_if_err("Invalid wmi handle"); 429 return QDF_STATUS_E_INVAL; 430 } 431 432 return wmi_unified_d0wow_disable_send(wmi_handle, TGT_WILDCARD_PDEV_ID); 433 } 434 #else 435 QDF_STATUS target_if_pmo_psoc_send_d0wow_enable_req( 436 struct wlan_objmgr_psoc *psoc) 437 { 438 return QDF_STATUS_E_INVAL; 439 } 440 441 QDF_STATUS target_if_pmo_psoc_send_d0wow_disable_req( 442 struct wlan_objmgr_psoc *psoc) 443 { 444 return QDF_STATUS_E_INVAL; 445 } 446 #endif 447 448 void target_if_pmo_set_wow_enable_ack_failed(struct wlan_objmgr_psoc *psoc) 449 { 450 wmi_unified_t wmi_handle; 451 452 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 453 if (!wmi_handle) { 454 target_if_err("Invalid wmi handle"); 455 return; 456 } 457 458 return wmi_set_wow_enable_ack_failed(wmi_handle); 459 } 460 461