1 /* 2 * Copyright (c) 2013-2021 The Linux Foundation. All rights reserved. 3 * Copyright (c) 2021-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_features.c 22 * This file contains different features related functions like WoW, 23 * Offloads, TDLS etc. 24 */ 25 26 /* Header files */ 27 28 #include "cds_ieee80211_common.h" /* ieee80211_frame */ 29 #include "wma.h" 30 #include "wma_api.h" 31 #include "cds_api.h" 32 #include "wmi_unified_api.h" 33 #include "wlan_qct_sys.h" 34 #include "wni_api.h" 35 #include "ani_global.h" 36 #include "wmi_unified.h" 37 #include "wni_cfg.h" 38 #include <cdp_txrx_tx_delay.h> 39 #include <cdp_txrx_peer_ops.h> 40 41 #include "qdf_nbuf.h" 42 #include "qdf_types.h" 43 #include "qdf_mem.h" 44 #include "qdf_util.h" 45 46 #include "wma_types.h" 47 #include "lim_api.h" 48 #include "lim_session_utils.h" 49 #include "cfg_ucfg_api.h" 50 #include "cds_utils.h" 51 #include "cfg_qos.h" 52 #if !defined(REMOVE_PKT_LOG) 53 #include "pktlog_ac.h" 54 #endif /* REMOVE_PKT_LOG */ 55 56 #include "dbglog_host.h" 57 #include "csr_api.h" 58 #include "ol_fw.h" 59 60 #include "wma_internal.h" 61 #include "wma_nan_datapath.h" 62 #include <cdp_txrx_handle.h> 63 #include "wlan_pmo_ucfg_api.h" 64 #include <target_if_scan.h> 65 #include "wlan_reg_services_api.h" 66 #include "wlan_roam_debug.h" 67 #include <wlan_cp_stats_mc_ucfg_api.h> 68 #ifdef WLAN_FEATURE_NAN 69 #include "target_if_nan.h" 70 #endif 71 #include "wlan_scan_api.h" 72 #include "spatial_reuse_api.h" 73 #include "wlan_cm_api.h" 74 #include <wlan_crypto_global_api.h> 75 #include "cdp_txrx_host_stats.h" 76 #include "target_if_cm_roam_event.h" 77 #include <wlan_mlo_mgr_cmn.h> 78 #include "hif.h" 79 #include "wlan_cmn_ieee80211.h" 80 #include "wlan_mlo_mgr_cmn.h" 81 #include "wlan_mlo_mgr_peer.h" 82 #include "wlan_mlo_mgr_sta.h" 83 #include "wlan_cp_stats_mc_defs.h" 84 85 86 /** 87 * WMA_SET_VDEV_IE_SOURCE_HOST - Flag to identify the source of VDEV SET IE 88 * command. The value is 0x0 for the VDEV SET IE WMI commands from mobile 89 * MCL platform. 90 */ 91 #define WMA_SET_VDEV_IE_SOURCE_HOST 0x0 92 93 /* 94 * Max AMPDU Tx Aggr supported size 95 */ 96 #define ADDBA_TXAGGR_SIZE_HELIUM 64 97 #define ADDBA_TXAGGR_SIZE_LITHIUM 256 98 #define ADDBA_TXAGGR_SIZE_512 512 99 #define ADDBA_TXAGGR_SIZE_BERYLLIUM 1024 100 101 static bool is_wakeup_event_console_logs_enabled = false; 102 wma_set_wakeup_logs_to_console(bool value)103 void wma_set_wakeup_logs_to_console(bool value) 104 { 105 is_wakeup_event_console_logs_enabled = value; 106 } 107 108 #if defined(FEATURE_WLAN_DIAG_SUPPORT) 109 /** 110 * qdf_wma_wow_wakeup_stats_event()- send wow wakeup stats 111 * @tp_wma_handle wma: WOW wakeup packet counter 112 * 113 * This function sends wow wakeup stats diag event 114 * 115 * Return: void. 116 */ qdf_wma_wow_wakeup_stats_event(tp_wma_handle wma)117 static inline void qdf_wma_wow_wakeup_stats_event(tp_wma_handle wma) 118 { 119 QDF_STATUS status; 120 struct wake_lock_stats stats = {0}; 121 122 WLAN_HOST_DIAG_EVENT_DEF(wow_stats, 123 struct host_event_wlan_powersave_wow_stats); 124 125 status = ucfg_mc_cp_stats_get_psoc_wake_lock_stats(wma->psoc, &stats); 126 if (QDF_IS_STATUS_ERROR(status)) 127 return; 128 qdf_mem_zero(&wow_stats, sizeof(wow_stats)); 129 130 wow_stats.wow_bcast_wake_up_count = stats.bcast_wake_up_count; 131 wow_stats.wow_ipv4_mcast_wake_up_count = stats.ipv4_mcast_wake_up_count; 132 wow_stats.wow_ipv6_mcast_wake_up_count = stats.ipv6_mcast_wake_up_count; 133 wow_stats.wow_ipv6_mcast_ra_stats = stats.ipv6_mcast_ra_stats; 134 wow_stats.wow_ipv6_mcast_ns_stats = stats.ipv6_mcast_ns_stats; 135 wow_stats.wow_ipv6_mcast_na_stats = stats.ipv6_mcast_na_stats; 136 wow_stats.wow_pno_match_wake_up_count = stats.pno_match_wake_up_count; 137 wow_stats.wow_pno_complete_wake_up_count = 138 stats.pno_complete_wake_up_count; 139 wow_stats.wow_gscan_wake_up_count = stats.gscan_wake_up_count; 140 wow_stats.wow_low_rssi_wake_up_count = stats.low_rssi_wake_up_count; 141 wow_stats.wow_rssi_breach_wake_up_count = 142 stats.rssi_breach_wake_up_count; 143 wow_stats.wow_icmpv4_count = stats.icmpv4_count; 144 wow_stats.wow_icmpv6_count = stats.icmpv6_count; 145 wow_stats.wow_oem_response_wake_up_count = 146 stats.oem_response_wake_up_count; 147 148 WLAN_HOST_DIAG_EVENT_REPORT(&wow_stats, EVENT_WLAN_POWERSAVE_WOW_STATS); 149 } 150 #else qdf_wma_wow_wakeup_stats_event(tp_wma_handle wma)151 static inline void qdf_wma_wow_wakeup_stats_event(tp_wma_handle wma) 152 { 153 return; 154 } 155 #endif 156 157 #ifdef FEATURE_WLAN_AUTO_SHUTDOWN 158 /** 159 * wma_wake_reason_auto_shutdown() - to post auto shutdown event to sme 160 * 161 * Return: 0 for success or error code 162 */ wma_wake_reason_auto_shutdown(void)163 static int wma_wake_reason_auto_shutdown(void) 164 { 165 QDF_STATUS qdf_status; 166 struct scheduler_msg sme_msg = { 0 }; 167 168 sme_msg.type = eWNI_SME_AUTO_SHUTDOWN_IND; 169 qdf_status = scheduler_post_message(QDF_MODULE_ID_WMA, 170 QDF_MODULE_ID_SME, 171 QDF_MODULE_ID_SME, &sme_msg); 172 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) 173 wma_err("Fail to post eWNI_SME_AUTO_SHUTDOWN_IND msg to SME"); 174 175 return qdf_status_to_os_return(qdf_status); 176 } 177 #else wma_wake_reason_auto_shutdown(void)178 static inline int wma_wake_reason_auto_shutdown(void) 179 { 180 return 0; 181 } 182 #endif /* FEATURE_WLAN_AUTO_SHUTDOWN */ 183 184 #ifdef FEATURE_WLAN_SCAN_PNO wma_wake_reason_nlod(t_wma_handle * wma,uint8_t vdev_id)185 static int wma_wake_reason_nlod(t_wma_handle *wma, uint8_t vdev_id) 186 { 187 wmi_nlo_event nlo_event = { .vdev_id = vdev_id }; 188 WMI_NLO_MATCH_EVENTID_param_tlvs param = { .fixed_param = &nlo_event }; 189 190 return target_if_nlo_match_event_handler(wma, (uint8_t *)¶m, 191 sizeof(param)); 192 } 193 #else wma_wake_reason_nlod(t_wma_handle * wma,uint8_t vdev_id)194 static inline int wma_wake_reason_nlod(t_wma_handle *wma, uint8_t vdev_id) 195 { 196 return 0; 197 } 198 #endif /* FEATURE_WLAN_SCAN_PNO */ 199 200 #ifdef WLAN_FEATURE_NAN 201 /** 202 * wma_nan_rsp_handler_callback() - call NAN Discovery event handler 203 * @handle: wma handle 204 * @event: event buffer 205 * @len: buffer length 206 * 207 * Return: 0 for success or error code 208 */ wma_nan_rsp_handler_callback(void * handle,uint8_t * event,uint32_t len)209 static int wma_nan_rsp_handler_callback(void *handle, uint8_t *event, 210 uint32_t len) 211 { 212 return target_if_nan_rsp_handler(handle, event, len); 213 } 214 #else wma_nan_rsp_handler_callback(void * handle,uint8_t * event,uint32_t len)215 static inline int wma_nan_rsp_handler_callback(void *handle, uint8_t *event, 216 uint32_t len) 217 { 218 return 0; 219 } 220 #endif 221 222 /** 223 * wma_get_snr() - get RSSI from fw 224 * @psnr_req: request params 225 * 226 * Return: QDF status 227 */ wma_get_snr(tAniGetSnrReq * psnr_req)228 QDF_STATUS wma_get_snr(tAniGetSnrReq *psnr_req) 229 { 230 tAniGetSnrReq *psnr_req_bkp; 231 tp_wma_handle wma_handle = NULL; 232 struct wma_txrx_node *intr; 233 234 wma_handle = cds_get_context(QDF_MODULE_ID_WMA); 235 if (!wma_handle) 236 return QDF_STATUS_E_FAULT; 237 238 intr = &wma_handle->interfaces[psnr_req->sessionId]; 239 /* command is in progress */ 240 if (intr->psnr_req) { 241 wma_err("previous snr request is pending"); 242 return QDF_STATUS_SUCCESS; 243 } 244 245 psnr_req_bkp = qdf_mem_malloc(sizeof(tAniGetSnrReq)); 246 if (!psnr_req_bkp) 247 return QDF_STATUS_E_NOMEM; 248 249 qdf_mem_zero(psnr_req_bkp, sizeof(tAniGetSnrReq)); 250 psnr_req_bkp->pDevContext = psnr_req->pDevContext; 251 psnr_req_bkp->snrCallback = psnr_req->snrCallback; 252 intr->psnr_req = (void *)psnr_req_bkp; 253 254 if (wmi_unified_snr_cmd(wma_handle->wmi_handle, 255 psnr_req->sessionId)) { 256 wma_err("Failed to send host stats request to fw"); 257 qdf_mem_free(psnr_req_bkp); 258 intr->psnr_req = NULL; 259 return QDF_STATUS_E_FAILURE; 260 } 261 262 return QDF_STATUS_SUCCESS; 263 } 264 wma_get_rx_retry_cnt(struct mac_context * mac,uint8_t vdev_id,uint8_t * mac_addr)265 void wma_get_rx_retry_cnt(struct mac_context *mac, uint8_t vdev_id, 266 uint8_t *mac_addr) 267 { 268 struct cdp_peer_stats *peer_stats; 269 QDF_STATUS status; 270 271 peer_stats = qdf_mem_malloc(sizeof(*peer_stats)); 272 if (!peer_stats) 273 return; 274 275 status = cdp_host_get_peer_stats(cds_get_context(QDF_MODULE_ID_SOC), 276 vdev_id, mac_addr, peer_stats); 277 278 if (QDF_IS_STATUS_ERROR(status)) { 279 wma_err("Failed to get peer stats"); 280 goto exit; 281 } 282 283 mac->rx_retry_cnt = peer_stats->rx.rx_retries; 284 wma_debug("Rx retry count %d, Peer" QDF_MAC_ADDR_FMT, mac->rx_retry_cnt, 285 QDF_MAC_ADDR_REF(mac_addr)); 286 287 exit: 288 qdf_mem_free(peer_stats); 289 } 290 291 /** 292 * wma_process_link_status_req() - process link status request from UMAC 293 * @wma: wma handle 294 * @pGetLinkStatus: get link params 295 * 296 * Return: none 297 */ wma_process_link_status_req(tp_wma_handle wma,tAniGetLinkStatus * pGetLinkStatus)298 void wma_process_link_status_req(tp_wma_handle wma, 299 tAniGetLinkStatus *pGetLinkStatus) 300 { 301 struct link_status_params cmd = {0}; 302 struct wma_txrx_node *iface = 303 &wma->interfaces[pGetLinkStatus->sessionId]; 304 305 if (iface->plink_status_req) { 306 wma_err("previous link status request is pending,deleting the new request"); 307 qdf_mem_free(pGetLinkStatus); 308 return; 309 } 310 311 iface->plink_status_req = pGetLinkStatus; 312 cmd.vdev_id = pGetLinkStatus->sessionId; 313 if (wmi_unified_link_status_req_cmd(wma->wmi_handle, &cmd)) { 314 wma_err("Failed to send WMI link status request to fw"); 315 iface->plink_status_req = NULL; 316 goto end; 317 } 318 319 return; 320 321 end: 322 wma_post_link_status(pGetLinkStatus, LINK_STATUS_LEGACY); 323 } 324 325 #ifdef WLAN_FEATURE_TSF 326 327 #if defined(WLAN_FEATURE_TSF_AUTO_REPORT) || defined(QCA_GET_TSF_VIA_REG) 328 static inline void wma_vdev_tsf_set_mac_id_tsf_id(struct stsf * ptsf,uint32_t mac_id,uint32_t mac_id_valid,uint32_t tsf_id,uint32_t tsf_id_valid)329 wma_vdev_tsf_set_mac_id_tsf_id(struct stsf *ptsf, uint32_t mac_id, 330 uint32_t mac_id_valid, uint32_t tsf_id, 331 uint32_t tsf_id_valid) 332 { 333 ptsf->mac_id = mac_id; 334 ptsf->mac_id_valid = mac_id_valid; 335 ptsf->tsf_id = tsf_id; 336 ptsf->tsf_id_valid = tsf_id_valid; 337 338 wma_nofl_debug("mac_id %d mac_id_valid %d tsf_id %d tsf_id_valid %d", 339 ptsf->mac_id, ptsf->mac_id_valid, ptsf->tsf_id, 340 ptsf->tsf_id_valid); 341 } 342 #else /* !(WLAN_FEATURE_TSF_AUTO_REPORT || QCA_GET_TSF_VIA_REG) */ 343 static inline void wma_vdev_tsf_set_mac_id_tsf_id(struct stsf * ptsf,uint32_t mac_id,uint32_t mac_id_valid,uint32_t tsf_id,uint32_t tsf_id_valid)344 wma_vdev_tsf_set_mac_id_tsf_id(struct stsf *ptsf, uint32_t mac_id, 345 uint32_t mac_id_valid, uint32_t tsf_id, 346 uint32_t tsf_id_valid) 347 { 348 } 349 #endif /* WLAN_FEATURE_TSF_AUTO_REPORT || QCA_GET_TSF_VIA_REG */ 350 351 /** 352 * wma_vdev_tsf_handler() - handle tsf event indicated by FW 353 * @handle: wma context 354 * @data: event buffer 355 * @data len: length of event buffer 356 * 357 * Return: 0 on success 358 */ wma_vdev_tsf_handler(void * handle,uint8_t * data,uint32_t data_len)359 int wma_vdev_tsf_handler(void *handle, uint8_t *data, uint32_t data_len) 360 { 361 struct scheduler_msg tsf_msg = {0}; 362 WMI_VDEV_TSF_REPORT_EVENTID_param_tlvs *param_buf; 363 wmi_vdev_tsf_report_event_fixed_param *tsf_event; 364 struct stsf *ptsf; 365 366 if (!data) { 367 wma_err("invalid pointer"); 368 return -EINVAL; 369 } 370 ptsf = qdf_mem_malloc(sizeof(*ptsf)); 371 if (!ptsf) 372 return -ENOMEM; 373 374 param_buf = (WMI_VDEV_TSF_REPORT_EVENTID_param_tlvs *)data; 375 tsf_event = param_buf->fixed_param; 376 377 ptsf->vdev_id = tsf_event->vdev_id; 378 ptsf->tsf_low = tsf_event->tsf_low; 379 ptsf->tsf_high = tsf_event->tsf_high; 380 ptsf->soc_timer_low = tsf_event->qtimer_low; 381 ptsf->soc_timer_high = tsf_event->qtimer_high; 382 ptsf->global_tsf_low = tsf_event->wlan_global_tsf_low; 383 ptsf->global_tsf_high = tsf_event->wlan_global_tsf_high; 384 wma_nofl_debug("receive WMI_VDEV_TSF_REPORT_EVENTID on %d, tsf: %d %d", 385 ptsf->vdev_id, ptsf->tsf_low, ptsf->tsf_high); 386 387 wma_nofl_debug("g_tsf: %d %d; soc_timer: %d %d", 388 ptsf->global_tsf_low, ptsf->global_tsf_high, 389 ptsf->soc_timer_low, ptsf->soc_timer_high); 390 391 wma_vdev_tsf_set_mac_id_tsf_id(ptsf, tsf_event->mac_id, 392 tsf_event->mac_id_valid, 393 tsf_event->tsf_id, 394 tsf_event->tsf_id_valid); 395 tsf_msg.type = eWNI_SME_TSF_EVENT; 396 tsf_msg.bodyptr = ptsf; 397 tsf_msg.bodyval = 0; 398 399 if (QDF_STATUS_SUCCESS != 400 scheduler_post_message(QDF_MODULE_ID_WMA, 401 QDF_MODULE_ID_SME, 402 QDF_MODULE_ID_SME, &tsf_msg)) { 403 qdf_mem_free(ptsf); 404 return -EINVAL; 405 } 406 return 0; 407 } 408 409 #if defined(QCA_WIFI_3_0) || defined(WLAN_FEATURE_TSF_TIMER_SYNC) 410 #define TSF_FW_ACTION_CMD TSF_TSTAMP_QTIMER_CAPTURE_REQ 411 #else 412 #define TSF_FW_ACTION_CMD TSF_TSTAMP_CAPTURE_REQ 413 #endif 414 /** 415 * wma_capture_tsf() - send wmi to fw to capture tsf 416 * @wma_handle: wma handler 417 * @vdev_id: vdev id 418 * 419 * Return: wmi send state 420 */ wma_capture_tsf(tp_wma_handle wma_handle,uint32_t vdev_id)421 QDF_STATUS wma_capture_tsf(tp_wma_handle wma_handle, uint32_t vdev_id) 422 { 423 QDF_STATUS status; 424 wmi_buf_t buf; 425 wmi_vdev_tsf_tstamp_action_cmd_fixed_param *cmd; 426 int len = sizeof(*cmd); 427 428 buf = wmi_buf_alloc(wma_handle->wmi_handle, len); 429 if (!buf) 430 return QDF_STATUS_E_NOMEM; 431 432 cmd = (wmi_vdev_tsf_tstamp_action_cmd_fixed_param *) wmi_buf_data(buf); 433 cmd->vdev_id = vdev_id; 434 cmd->tsf_action = TSF_FW_ACTION_CMD; 435 wma_debug("vdev_id %u, tsf_cmd: %d", cmd->vdev_id, cmd->tsf_action); 436 437 WMITLV_SET_HDR(&cmd->tlv_header, 438 WMITLV_TAG_STRUC_wmi_vdev_tsf_tstamp_action_cmd_fixed_param, 439 WMITLV_GET_STRUCT_TLVLEN( 440 wmi_vdev_tsf_tstamp_action_cmd_fixed_param)); 441 442 status = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len, 443 WMI_VDEV_TSF_TSTAMP_ACTION_CMDID); 444 if (QDF_IS_STATUS_ERROR(status)) 445 wmi_buf_free(buf); 446 447 return status; 448 } 449 450 /** 451 * wma_reset_tsf_gpio() - send wmi to fw to reset GPIO 452 * @wma_handle: wma handler 453 * @vdev_id: vdev id 454 * 455 * Return: wmi send state 456 */ wma_reset_tsf_gpio(tp_wma_handle wma_handle,uint32_t vdev_id)457 QDF_STATUS wma_reset_tsf_gpio(tp_wma_handle wma_handle, uint32_t vdev_id) 458 { 459 QDF_STATUS status; 460 wmi_buf_t buf; 461 wmi_vdev_tsf_tstamp_action_cmd_fixed_param *cmd; 462 int len = sizeof(*cmd); 463 uint8_t *buf_ptr; 464 465 buf = wmi_buf_alloc(wma_handle->wmi_handle, len); 466 if (!buf) 467 return QDF_STATUS_E_NOMEM; 468 469 buf_ptr = (uint8_t *) wmi_buf_data(buf); 470 cmd = (wmi_vdev_tsf_tstamp_action_cmd_fixed_param *) buf_ptr; 471 cmd->vdev_id = vdev_id; 472 cmd->tsf_action = TSF_TSTAMP_CAPTURE_RESET; 473 474 wma_debug("vdev_id %u, TSF_TSTAMP_CAPTURE_RESET", cmd->vdev_id); 475 476 WMITLV_SET_HDR(&cmd->tlv_header, 477 WMITLV_TAG_STRUC_wmi_vdev_tsf_tstamp_action_cmd_fixed_param, 478 WMITLV_GET_STRUCT_TLVLEN( 479 wmi_vdev_tsf_tstamp_action_cmd_fixed_param)); 480 481 status = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len, 482 WMI_VDEV_TSF_TSTAMP_ACTION_CMDID); 483 if (QDF_IS_STATUS_ERROR(status)) 484 wmi_buf_free(buf); 485 486 return status; 487 } 488 489 /** 490 * wma_set_tsf_gpio_pin() - send wmi cmd to configure gpio pin 491 * @handle: wma handler 492 * @pin: GPIO pin id 493 * 494 * Return: QDF_STATUS 495 */ wma_set_tsf_gpio_pin(WMA_HANDLE handle,uint32_t pin)496 QDF_STATUS wma_set_tsf_gpio_pin(WMA_HANDLE handle, uint32_t pin) 497 { 498 tp_wma_handle wma = (tp_wma_handle)handle; 499 struct pdev_params pdev_param = {0}; 500 int32_t ret; 501 struct wmi_unified *wmi_handle; 502 503 if (wma_validate_handle(wma)) 504 return QDF_STATUS_E_INVAL; 505 506 wmi_handle = wma->wmi_handle; 507 if (wmi_validate_handle(wmi_handle)) 508 return QDF_STATUS_E_INVAL; 509 510 wma_debug("set tsf gpio pin: %d", pin); 511 512 pdev_param.param_id = wmi_pdev_param_wnts_config; 513 pdev_param.param_value = pin; 514 ret = wmi_unified_pdev_param_send(wmi_handle, 515 &pdev_param, 516 WMA_WILDCARD_PDEV_ID); 517 if (ret) { 518 wma_err("Failed to set tsf gpio pin (status=%d)", ret); 519 return QDF_STATUS_E_FAILURE; 520 } 521 return QDF_STATUS_SUCCESS; 522 } 523 524 #ifdef WLAN_FEATURE_TSF_AUTO_REPORT wma_set_tsf_auto_report(WMA_HANDLE handle,uint32_t vdev_id,uint32_t param_id,bool ena)525 QDF_STATUS wma_set_tsf_auto_report(WMA_HANDLE handle, uint32_t vdev_id, 526 uint32_t param_id, bool ena) 527 { 528 wmi_vdev_tsf_tstamp_action_cmd_fixed_param *cmd; 529 tp_wma_handle wma = (tp_wma_handle)handle; 530 struct wmi_unified *wmi_handle; 531 int len = sizeof(*cmd); 532 QDF_STATUS status; 533 uint8_t *buf_ptr; 534 wmi_buf_t buf; 535 536 if (param_id != GEN_PARAM_TSF_AUTO_REPORT_ENABLE && 537 param_id != GEN_PARAM_TSF_AUTO_REPORT_DISABLE) 538 return QDF_STATUS_E_FAILURE; 539 540 wmi_handle = wma->wmi_handle; 541 if (wmi_validate_handle(wmi_handle)) 542 return QDF_STATUS_E_INVAL; 543 544 buf = wmi_buf_alloc(wmi_handle, len); 545 if (!buf) 546 return QDF_STATUS_E_NOMEM; 547 548 buf_ptr = (uint8_t *)wmi_buf_data(buf); 549 cmd = (wmi_vdev_tsf_tstamp_action_cmd_fixed_param *)buf_ptr; 550 cmd->vdev_id = vdev_id; 551 cmd->tsf_action = ena ? TSF_TSTAMP_AUTO_REPORT_ENABLE : 552 TSF_TSTAMP_AUTO_REPORT_DISABLE; 553 554 wma_debug("vdev_id %u tsf_action %d", cmd->vdev_id, cmd->tsf_action); 555 556 WMITLV_SET_HDR( 557 &cmd->tlv_header, 558 WMITLV_TAG_STRUC_wmi_vdev_tsf_tstamp_action_cmd_fixed_param, 559 WMITLV_GET_STRUCT_TLVLEN( 560 wmi_vdev_tsf_tstamp_action_cmd_fixed_param)); 561 562 status = wmi_unified_cmd_send(wmi_handle, buf, len, 563 WMI_VDEV_TSF_TSTAMP_ACTION_CMDID); 564 if (QDF_IS_STATUS_ERROR(status)) 565 wmi_buf_free(buf); 566 567 return status; 568 } 569 #endif /* WLAN_FEATURE_TSF_AUTO_REPORT */ 570 #endif 571 572 /** 573 * wma_set_wisa_params(): Set WISA features related params in FW 574 * @wma_handle: WMA handle 575 * @wisa: Pointer to WISA param struct 576 * 577 * Return: CDF status 578 */ wma_set_wisa_params(tp_wma_handle wma_handle,struct sir_wisa_params * wisa)579 QDF_STATUS wma_set_wisa_params(tp_wma_handle wma_handle, 580 struct sir_wisa_params *wisa) 581 { 582 QDF_STATUS status; 583 wmi_buf_t buf; 584 wmi_vdev_wisa_cmd_fixed_param *cmd; 585 int len = sizeof(*cmd); 586 587 buf = wmi_buf_alloc(wma_handle->wmi_handle, len); 588 if (!buf) 589 return QDF_STATUS_E_NOMEM; 590 591 cmd = (wmi_vdev_wisa_cmd_fixed_param *) wmi_buf_data(buf); 592 cmd->wisa_mode = wisa->mode; 593 cmd->vdev_id = wisa->vdev_id; 594 595 WMITLV_SET_HDR(&cmd->tlv_header, 596 WMITLV_TAG_STRUC_wmi_vdev_wisa_cmd_fixed_param, 597 WMITLV_GET_STRUCT_TLVLEN( 598 wmi_vdev_wisa_cmd_fixed_param)); 599 600 status = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len, 601 WMI_VDEV_WISA_CMDID); 602 if (QDF_IS_STATUS_ERROR(status)) 603 wmi_buf_free(buf); 604 605 return status; 606 } 607 608 /** 609 * wma_process_dhcp_ind() - process dhcp indication from SME 610 * @wma_handle: wma handle 611 * @ta_dhcp_ind: DHCP indication 612 * 613 * Return: QDF Status 614 */ wma_process_dhcp_ind(WMA_HANDLE handle,tAniDHCPInd * ta_dhcp_ind)615 QDF_STATUS wma_process_dhcp_ind(WMA_HANDLE handle, 616 tAniDHCPInd *ta_dhcp_ind) 617 { 618 tp_wma_handle wma_handle = (tp_wma_handle) handle; 619 uint8_t vdev_id; 620 wmi_peer_set_param_cmd_fixed_param peer_set_param_fp = {0}; 621 622 if (wma_validate_handle(wma_handle)) 623 return QDF_STATUS_E_FAILURE; 624 625 if (!ta_dhcp_ind) { 626 wma_err("DHCP indication is NULL"); 627 return QDF_STATUS_E_FAILURE; 628 } 629 630 if (wma_find_vdev_id_by_addr(wma_handle, 631 ta_dhcp_ind->adapterMacAddr.bytes, 632 &vdev_id)) { 633 wma_err("Failed to find vdev id for DHCP indication"); 634 return QDF_STATUS_E_FAILURE; 635 } 636 637 wma_debug("WMA --> WMI_PEER_SET_PARAM triggered by DHCP, msgType=%s, device_mode=%d, macAddr=" QDF_MAC_ADDR_FMT, 638 ta_dhcp_ind->msgType == WMA_DHCP_START_IND ? 639 "WMA_DHCP_START_IND" : "WMA_DHCP_STOP_IND", 640 ta_dhcp_ind->device_mode, 641 QDF_MAC_ADDR_REF(ta_dhcp_ind->peerMacAddr.bytes)); 642 643 /* fill in values */ 644 peer_set_param_fp.vdev_id = vdev_id; 645 peer_set_param_fp.param_id = WMI_HOST_PEER_CRIT_PROTO_HINT_ENABLED; 646 if (WMA_DHCP_START_IND == ta_dhcp_ind->msgType) 647 peer_set_param_fp.param_value = 1; 648 else 649 peer_set_param_fp.param_value = 0; 650 WMI_CHAR_ARRAY_TO_MAC_ADDR(ta_dhcp_ind->peerMacAddr.bytes, 651 &peer_set_param_fp.peer_macaddr); 652 653 return wmi_unified_process_dhcp_ind(wma_handle->wmi_handle, 654 &peer_set_param_fp); 655 } 656 657 #if defined(WLAN_FEATURE_11BE) 658 static enum wlan_phymode wma_eht_chan_phy_mode(uint32_t freq,uint8_t dot11_mode,uint16_t bw_val,enum phy_ch_width chan_width)659 wma_eht_chan_phy_mode(uint32_t freq, uint8_t dot11_mode, uint16_t bw_val, 660 enum phy_ch_width chan_width) 661 { 662 if((dot11_mode == MLME_DOT11_MODE_11BE) || 663 (dot11_mode == MLME_DOT11_MODE_11BE_ONLY)) 664 { 665 if (wlan_reg_is_24ghz_ch_freq(freq)) { 666 if (bw_val == 20) 667 return WLAN_PHYMODE_11BEG_EHT20; 668 else if (bw_val == 40) 669 return WLAN_PHYMODE_11BEG_EHT40; 670 } else { 671 if (bw_val == 20) 672 return WLAN_PHYMODE_11BEA_EHT20; 673 else if (bw_val == 40) 674 return WLAN_PHYMODE_11BEA_EHT40; 675 else if (bw_val == 80) 676 return WLAN_PHYMODE_11BEA_EHT80; 677 else if (chan_width == CH_WIDTH_160MHZ) 678 return WLAN_PHYMODE_11BEA_EHT160; 679 else if (chan_width == CH_WIDTH_320MHZ) 680 return WLAN_PHYMODE_11BEA_EHT320; 681 } 682 } 683 684 return WLAN_PHYMODE_AUTO; 685 } 686 #else 687 static enum wlan_phymode wma_eht_chan_phy_mode(uint32_t freq,uint8_t dot11_mode,uint16_t bw_val,enum phy_ch_width chan_width)688 wma_eht_chan_phy_mode(uint32_t freq, uint8_t dot11_mode, uint16_t bw_val, 689 enum phy_ch_width chan_width) 690 { 691 return WLAN_PHYMODE_AUTO; 692 } 693 #endif 694 wma_chan_phy_mode(uint32_t freq,enum phy_ch_width chan_width,uint8_t dot11_mode)695 enum wlan_phymode wma_chan_phy_mode(uint32_t freq, enum phy_ch_width chan_width, 696 uint8_t dot11_mode) 697 { 698 enum wlan_phymode phymode = WLAN_PHYMODE_AUTO; 699 uint16_t bw_val = wlan_reg_get_bw_value(chan_width); 700 t_wma_handle *wma = cds_get_context(QDF_MODULE_ID_WMA); 701 702 if (!wma) 703 return WLAN_PHYMODE_AUTO; 704 705 if (chan_width >= CH_WIDTH_INVALID || !bw_val || 706 (wlan_reg_is_24ghz_ch_freq(freq) && bw_val > 40)) { 707 wma_err_rl("Invalid channel width %d freq %d", 708 chan_width, freq); 709 return WLAN_PHYMODE_AUTO; 710 } 711 712 if (wlan_reg_is_24ghz_ch_freq(freq)) { 713 if (((CH_WIDTH_5MHZ == chan_width) || 714 (CH_WIDTH_10MHZ == chan_width)) && 715 ((MLME_DOT11_MODE_11B == dot11_mode) || 716 (MLME_DOT11_MODE_11G == dot11_mode) || 717 (MLME_DOT11_MODE_11N == dot11_mode) || 718 (MLME_DOT11_MODE_ALL == dot11_mode) || 719 (MLME_DOT11_MODE_11AC == dot11_mode) || 720 (MLME_DOT11_MODE_11AX == dot11_mode))) 721 phymode = WLAN_PHYMODE_11G; 722 else { 723 switch (dot11_mode) { 724 case MLME_DOT11_MODE_11B: 725 if ((bw_val == 20) || (bw_val == 40)) 726 phymode = WLAN_PHYMODE_11B; 727 break; 728 case MLME_DOT11_MODE_11G: 729 if ((bw_val == 20) || (bw_val == 40)) 730 phymode = WLAN_PHYMODE_11G; 731 break; 732 case MLME_DOT11_MODE_11G_ONLY: 733 if ((bw_val == 20) || (bw_val == 40)) 734 phymode = WLAN_PHYMODE_11G_ONLY; 735 break; 736 case MLME_DOT11_MODE_11N: 737 case MLME_DOT11_MODE_11N_ONLY: 738 if (bw_val == 20) 739 phymode = WLAN_PHYMODE_11NG_HT20; 740 else if (bw_val == 40) 741 phymode = WLAN_PHYMODE_11NG_HT40; 742 break; 743 case MLME_DOT11_MODE_ALL: 744 case MLME_DOT11_MODE_11AC: 745 case MLME_DOT11_MODE_11AC_ONLY: 746 if (bw_val == 20) 747 phymode = WLAN_PHYMODE_11AC_VHT20_2G; 748 else if (bw_val == 40) 749 phymode = WLAN_PHYMODE_11AC_VHT40_2G; 750 break; 751 case MLME_DOT11_MODE_11AX: 752 case MLME_DOT11_MODE_11AX_ONLY: 753 if (20 == bw_val) 754 phymode = WLAN_PHYMODE_11AXG_HE20; 755 else if (40 == bw_val) 756 phymode = WLAN_PHYMODE_11AXG_HE40; 757 break; 758 default: 759 phymode = wma_eht_chan_phy_mode( 760 freq, 761 dot11_mode, 762 bw_val, 763 chan_width); 764 break; 765 } 766 } 767 } else if (wlan_reg_is_dsrc_freq(freq)) 768 phymode = WLAN_PHYMODE_11A; 769 else { 770 if (((CH_WIDTH_5MHZ == chan_width) || 771 (CH_WIDTH_10MHZ == chan_width)) && 772 ((MLME_DOT11_MODE_11A == dot11_mode) || 773 (MLME_DOT11_MODE_11N == dot11_mode) || 774 (MLME_DOT11_MODE_ALL == dot11_mode) || 775 (MLME_DOT11_MODE_11AC == dot11_mode) || 776 (MLME_DOT11_MODE_11AX == dot11_mode))) 777 phymode = WLAN_PHYMODE_11A; 778 else { 779 switch (dot11_mode) { 780 case MLME_DOT11_MODE_11A: 781 if (0 < bw_val) 782 phymode = WLAN_PHYMODE_11A; 783 break; 784 case MLME_DOT11_MODE_11N: 785 case MLME_DOT11_MODE_11N_ONLY: 786 if (bw_val == 20) 787 phymode = WLAN_PHYMODE_11NA_HT20; 788 else if (40 <= bw_val) 789 phymode = WLAN_PHYMODE_11NA_HT40; 790 break; 791 case MLME_DOT11_MODE_ALL: 792 case MLME_DOT11_MODE_11AC: 793 case MLME_DOT11_MODE_11AC_ONLY: 794 if (bw_val == 20) 795 phymode = WLAN_PHYMODE_11AC_VHT20; 796 else if (bw_val == 40) 797 phymode = WLAN_PHYMODE_11AC_VHT40; 798 else if (bw_val == 80) 799 phymode = WLAN_PHYMODE_11AC_VHT80; 800 else if (chan_width == CH_WIDTH_160MHZ) 801 phymode = WLAN_PHYMODE_11AC_VHT160; 802 else if (chan_width == CH_WIDTH_80P80MHZ) 803 phymode = WLAN_PHYMODE_11AC_VHT80_80; 804 break; 805 case MLME_DOT11_MODE_11AX: 806 case MLME_DOT11_MODE_11AX_ONLY: 807 if (20 == bw_val) 808 phymode = WLAN_PHYMODE_11AXA_HE20; 809 else if (40 == bw_val) 810 phymode = WLAN_PHYMODE_11AXA_HE40; 811 else if (80 == bw_val) 812 phymode = WLAN_PHYMODE_11AXA_HE80; 813 else if (CH_WIDTH_160MHZ == chan_width) 814 phymode = WLAN_PHYMODE_11AXA_HE160; 815 else if (CH_WIDTH_80P80MHZ == chan_width) 816 phymode = WLAN_PHYMODE_11AXA_HE80_80; 817 break; 818 default: 819 phymode = wma_eht_chan_phy_mode( 820 freq, 821 dot11_mode, 822 bw_val, 823 chan_width); 824 break; 825 } 826 } 827 } 828 829 wma_debug("phymode %d freq %d ch_width %d dot11_mode %d", 830 phymode, freq, chan_width, dot11_mode); 831 832 QDF_ASSERT(phymode != WLAN_PHYMODE_AUTO); 833 return phymode; 834 } 835 836 /** 837 * wma_get_link_speed() -send command to get linkspeed 838 * @handle: wma handle 839 * @pLinkSpeed: link speed info 840 * 841 * Return: QDF status 842 */ wma_get_link_speed(WMA_HANDLE handle,struct link_speed_info * pLinkSpeed)843 QDF_STATUS wma_get_link_speed(WMA_HANDLE handle, 844 struct link_speed_info *pLinkSpeed) 845 { 846 tp_wma_handle wma_handle = (tp_wma_handle) handle; 847 wmi_mac_addr peer_macaddr; 848 struct wmi_unified *wmi_handle; 849 850 if (wma_validate_handle(wma_handle)) 851 return QDF_STATUS_E_INVAL; 852 853 wmi_handle = wma_handle->wmi_handle; 854 if (wmi_validate_handle(wmi_handle)) 855 return QDF_STATUS_E_INVAL; 856 857 if (!wmi_service_enabled(wmi_handle, 858 wmi_service_estimate_linkspeed)) { 859 wma_err("Linkspeed feature bit not enabled Sending value 0 as link speed"); 860 wma_send_link_speed(0); 861 return QDF_STATUS_E_FAILURE; 862 } 863 /* Copy the peer macaddress to the wma buffer */ 864 WMI_CHAR_ARRAY_TO_MAC_ADDR(pLinkSpeed->peer_macaddr.bytes, 865 &peer_macaddr); 866 wma_debug("pLinkSpeed->peerMacAddr: "QDF_MAC_ADDR_FMT", peer_macaddr.mac_addr31to0: 0x%x, peer_macaddr.mac_addr47to32: 0x%x", 867 QDF_MAC_ADDR_REF(pLinkSpeed->peer_macaddr.bytes), 868 peer_macaddr.mac_addr31to0, 869 peer_macaddr.mac_addr47to32); 870 if (wmi_unified_get_link_speed_cmd(wmi_handle, peer_macaddr)) { 871 return QDF_STATUS_E_FAILURE; 872 } 873 874 return QDF_STATUS_SUCCESS; 875 } 876 wma_get_isolation(tp_wma_handle wma)877 QDF_STATUS wma_get_isolation(tp_wma_handle wma) 878 { 879 wmi_coex_get_antenna_isolation_cmd_fixed_param *cmd; 880 wmi_buf_t wmi_buf; 881 uint32_t len; 882 uint8_t *buf_ptr; 883 struct wmi_unified *wmi_handle; 884 885 wma_debug("get isolation"); 886 887 if (wma_validate_handle(wma)) 888 return QDF_STATUS_E_INVAL; 889 890 wmi_handle = wma->wmi_handle; 891 if (wmi_validate_handle(wma->wmi_handle)) 892 return QDF_STATUS_E_INVAL; 893 894 len = sizeof(wmi_coex_get_antenna_isolation_cmd_fixed_param); 895 wmi_buf = wmi_buf_alloc(wmi_handle, len); 896 if (!wmi_buf) { 897 wma_err("wmi_buf_alloc failed"); 898 return QDF_STATUS_E_NOMEM; 899 } 900 buf_ptr = (uint8_t *)wmi_buf_data(wmi_buf); 901 902 cmd = (wmi_coex_get_antenna_isolation_cmd_fixed_param *)buf_ptr; 903 WMITLV_SET_HDR( 904 &cmd->tlv_header, 905 WMITLV_TAG_STRUC_wmi_coex_get_antenna_isolation_cmd_fixed_param, 906 WMITLV_GET_STRUCT_TLVLEN( 907 wmi_coex_get_antenna_isolation_cmd_fixed_param)); 908 909 if (wmi_unified_cmd_send(wmi_handle, wmi_buf, len, 910 WMI_COEX_GET_ANTENNA_ISOLATION_CMDID)) { 911 wma_err("Failed to get isolation request from fw"); 912 wmi_buf_free(wmi_buf); 913 return QDF_STATUS_E_FAILURE; 914 } 915 916 return QDF_STATUS_SUCCESS; 917 } 918 919 /** 920 * wma_add_beacon_filter() - Issue WMI command to set beacon filter 921 * @wma: wma handler 922 * @filter_params: beacon_filter_param to set 923 * 924 * Return: Return QDF_STATUS 925 */ wma_add_beacon_filter(WMA_HANDLE handle,struct beacon_filter_param * filter_params)926 QDF_STATUS wma_add_beacon_filter(WMA_HANDLE handle, 927 struct beacon_filter_param *filter_params) 928 { 929 int i; 930 wmi_buf_t wmi_buf; 931 u_int8_t *buf; 932 A_UINT32 *ie_map; 933 int ret; 934 struct wma_txrx_node *iface; 935 tp_wma_handle wma = (tp_wma_handle) handle; 936 struct wmi_unified *wmi_handle; 937 938 wmi_add_bcn_filter_cmd_fixed_param *cmd; 939 int len = sizeof(wmi_add_bcn_filter_cmd_fixed_param); 940 941 len += WMI_TLV_HDR_SIZE; 942 len += BCN_FLT_MAX_ELEMS_IE_LIST * sizeof(A_UINT32); 943 944 /* for ext ie map */ 945 len += WMI_TLV_HDR_SIZE; 946 len += BCN_FLT_MAX_ELEMS_IE_LIST * sizeof(A_UINT32); 947 948 if (wma_validate_handle(wma)) 949 return QDF_STATUS_E_INVAL; 950 951 wmi_handle = wma->wmi_handle; 952 if (wmi_validate_handle(wma->wmi_handle)) 953 return QDF_STATUS_E_INVAL; 954 955 iface = &wma->interfaces[filter_params->vdev_id]; 956 qdf_mem_copy(&iface->beacon_filter, filter_params, 957 sizeof(struct beacon_filter_param)); 958 iface->beacon_filter_enabled = true; 959 960 wmi_buf = wmi_buf_alloc(wmi_handle, len); 961 if (!wmi_buf) 962 return QDF_STATUS_E_NOMEM; 963 964 buf = (u_int8_t *) wmi_buf_data(wmi_buf); 965 966 cmd = (wmi_add_bcn_filter_cmd_fixed_param *)wmi_buf_data(wmi_buf); 967 cmd->vdev_id = filter_params->vdev_id; 968 969 WMITLV_SET_HDR(&cmd->tlv_header, 970 WMITLV_TAG_STRUC_wmi_add_bcn_filter_cmd_fixed_param, 971 WMITLV_GET_STRUCT_TLVLEN( 972 wmi_add_bcn_filter_cmd_fixed_param)); 973 974 buf += sizeof(wmi_add_bcn_filter_cmd_fixed_param); 975 976 WMITLV_SET_HDR(buf, WMITLV_TAG_ARRAY_UINT32, 977 (BCN_FLT_MAX_ELEMS_IE_LIST * sizeof(u_int32_t))); 978 979 ie_map = (A_UINT32 *)(buf + WMI_TLV_HDR_SIZE); 980 for (i = 0; i < BCN_FLT_MAX_ELEMS_IE_LIST; i++) 981 ie_map[i] = filter_params->ie_map[i]; 982 983 wma_debug("Beacon filter ie map Hex dump:"); 984 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_DEBUG, 985 (uint8_t *)ie_map, 986 BCN_FLT_MAX_ELEMS_IE_LIST * sizeof(u_int32_t)); 987 988 buf += WMI_TLV_HDR_SIZE; 989 buf += BCN_FLT_MAX_ELEMS_IE_LIST * sizeof(A_UINT32); 990 991 WMITLV_SET_HDR(buf, WMITLV_TAG_ARRAY_UINT32, 992 (BCN_FLT_MAX_ELEMS_IE_LIST * sizeof(u_int32_t))); 993 994 ie_map = (A_UINT32 *)(buf + WMI_TLV_HDR_SIZE); 995 for (i = 0; i < BCN_FLT_MAX_ELEMS_IE_LIST; i++) 996 ie_map[i] = filter_params->ie_map[i + 8]; 997 998 wma_debug("Beacon filter ext ie map Hex dump:"); 999 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_DEBUG, 1000 (uint8_t *)ie_map, 1001 BCN_FLT_MAX_ELEMS_IE_LIST * sizeof(u_int32_t)); 1002 1003 ret = wmi_unified_cmd_send(wmi_handle, wmi_buf, len, 1004 WMI_ADD_BCN_FILTER_CMDID); 1005 if (ret) { 1006 wmi_buf_free(wmi_buf); 1007 return QDF_STATUS_E_FAILURE; 1008 } 1009 1010 return QDF_STATUS_SUCCESS; 1011 } 1012 1013 /** 1014 * wma_remove_beacon_filter() - Issue WMI command to remove beacon filter 1015 * @wma: wma handler 1016 * @filter_params: beacon_filter_params 1017 * 1018 * Return: Return QDF_STATUS 1019 */ wma_remove_beacon_filter(WMA_HANDLE handle,struct beacon_filter_param * filter_params)1020 QDF_STATUS wma_remove_beacon_filter(WMA_HANDLE handle, 1021 struct beacon_filter_param *filter_params) 1022 { 1023 wmi_buf_t buf; 1024 tp_wma_handle wma = (tp_wma_handle) handle; 1025 wmi_rmv_bcn_filter_cmd_fixed_param *cmd; 1026 int len = sizeof(wmi_rmv_bcn_filter_cmd_fixed_param); 1027 int ret; 1028 struct wmi_unified *wmi_handle; 1029 1030 if (wma_validate_handle(wma)) 1031 return QDF_STATUS_E_INVAL; 1032 1033 wmi_handle = wma->wmi_handle; 1034 if (wmi_validate_handle(wma->wmi_handle)) 1035 return QDF_STATUS_E_INVAL; 1036 1037 buf = wmi_buf_alloc(wmi_handle, len); 1038 if (!buf) 1039 return QDF_STATUS_E_NOMEM; 1040 1041 cmd = (wmi_rmv_bcn_filter_cmd_fixed_param *)wmi_buf_data(buf); 1042 cmd->vdev_id = filter_params->vdev_id; 1043 1044 WMITLV_SET_HDR(&cmd->tlv_header, 1045 WMITLV_TAG_STRUC_wmi_rmv_bcn_filter_cmd_fixed_param, 1046 WMITLV_GET_STRUCT_TLVLEN( 1047 wmi_rmv_bcn_filter_cmd_fixed_param)); 1048 1049 ret = wmi_unified_cmd_send(wmi_handle, buf, len, 1050 WMI_RMV_BCN_FILTER_CMDID); 1051 if (ret) { 1052 wmi_buf_free(buf); 1053 return QDF_STATUS_E_FAILURE; 1054 } 1055 1056 return QDF_STATUS_SUCCESS; 1057 } 1058 1059 /** 1060 * wma_send_adapt_dwelltime_params() - send adaptive dwelltime configuration 1061 * params to firmware 1062 * @wma_handle: wma handler 1063 * @dwelltime_params: pointer to dwelltime_params 1064 * 1065 * Return: QDF_STATUS_SUCCESS on success and QDF failure reason code for failure 1066 */ wma_send_adapt_dwelltime_params(WMA_HANDLE handle,struct adaptive_dwelltime_params * dwelltime_params)1067 QDF_STATUS wma_send_adapt_dwelltime_params(WMA_HANDLE handle, 1068 struct adaptive_dwelltime_params *dwelltime_params) 1069 { 1070 tp_wma_handle wma_handle = (tp_wma_handle) handle; 1071 struct wmi_adaptive_dwelltime_params wmi_param = {0}; 1072 int32_t err; 1073 1074 wmi_param.is_enabled = dwelltime_params->is_enabled; 1075 wmi_param.dwelltime_mode = dwelltime_params->dwelltime_mode; 1076 wmi_param.lpf_weight = dwelltime_params->lpf_weight; 1077 wmi_param.passive_mon_intval = dwelltime_params->passive_mon_intval; 1078 wmi_param.wifi_act_threshold = dwelltime_params->wifi_act_threshold; 1079 err = wmi_unified_send_adapt_dwelltime_params_cmd(wma_handle-> 1080 wmi_handle, &wmi_param); 1081 if (err) 1082 return QDF_STATUS_E_FAILURE; 1083 1084 return QDF_STATUS_SUCCESS; 1085 } 1086 wma_send_dbs_scan_selection_params(WMA_HANDLE handle,struct wmi_dbs_scan_sel_params * dbs_scan_params)1087 QDF_STATUS wma_send_dbs_scan_selection_params(WMA_HANDLE handle, 1088 struct wmi_dbs_scan_sel_params *dbs_scan_params) 1089 { 1090 tp_wma_handle wma_handle = (tp_wma_handle) handle; 1091 int32_t err; 1092 1093 err = wmi_unified_send_dbs_scan_sel_params_cmd(wma_handle-> 1094 wmi_handle, dbs_scan_params); 1095 if (err) 1096 return QDF_STATUS_E_FAILURE; 1097 1098 return QDF_STATUS_SUCCESS; 1099 } 1100 1101 /** 1102 * wma_unified_fw_profiling_cmd() - send FW profiling cmd to WLAN FW 1103 * @wma: wma handle 1104 * @cmd: Profiling command index 1105 * @value1: parameter1 value 1106 * @value2: parameter2 value 1107 * 1108 * Return: 0 for success else error code 1109 */ wma_unified_fw_profiling_cmd(wmi_unified_t wmi_handle,uint32_t cmd,uint32_t value1,uint32_t value2)1110 QDF_STATUS wma_unified_fw_profiling_cmd(wmi_unified_t wmi_handle, 1111 uint32_t cmd, uint32_t value1, uint32_t value2) 1112 { 1113 int ret; 1114 1115 ret = wmi_unified_fw_profiling_data_cmd(wmi_handle, cmd, 1116 value1, value2); 1117 if (ret) { 1118 wma_err("enable cmd Failed for id %d value %d", value1, value2); 1119 return ret; 1120 } 1121 1122 return QDF_STATUS_SUCCESS; 1123 } 1124 1125 /** 1126 * wma_wow_set_wake_time() - set timer pattern tlv, so that firmware will wake 1127 * up host after specified time is elapsed 1128 * @wma_handle: wma handle 1129 * @vdev_id: vdev id 1130 * @cookie: value to identify reason why host set up wake call. 1131 * @time: time in ms 1132 * 1133 * Return: QDF status 1134 */ wma_wow_set_wake_time(WMA_HANDLE wma_handle,uint8_t vdev_id,uint32_t cookie,uint32_t time)1135 static QDF_STATUS wma_wow_set_wake_time(WMA_HANDLE wma_handle, uint8_t vdev_id, 1136 uint32_t cookie, uint32_t time) 1137 { 1138 int ret; 1139 tp_wma_handle wma = (tp_wma_handle)wma_handle; 1140 1141 wma_debug("send timer pattern with time: %d and vdev = %d to fw", 1142 time, vdev_id); 1143 ret = wmi_unified_wow_timer_pattern_cmd(wma->wmi_handle, vdev_id, 1144 cookie, time); 1145 if (ret) { 1146 wma_err("Failed to send timer pattern to fw"); 1147 return QDF_STATUS_E_FAILURE; 1148 } 1149 1150 return QDF_STATUS_SUCCESS; 1151 } 1152 1153 #ifdef WLAN_POWER_MANAGEMENT_OFFLOAD 1154 /** 1155 * wma_check_and_set_wake_timer(): checks all interfaces and if any interface 1156 * has install_key pending, sets timer pattern in fw to wake up host after 1157 * specified time has elapsed. 1158 * @wma: wma handle 1159 * @time: time after which host wants to be awaken. 1160 * 1161 * Return: None 1162 */ wma_check_and_set_wake_timer(uint32_t time)1163 void wma_check_and_set_wake_timer(uint32_t time) 1164 { 1165 int i; 1166 struct wma_txrx_node *iface; 1167 bool is_set_key_in_progress = false; 1168 t_wma_handle *wma = cds_get_context(QDF_MODULE_ID_WMA); 1169 1170 if (!wma) 1171 return; 1172 1173 if (!wmi_service_enabled(wma->wmi_handle, 1174 wmi_service_wow_wakeup_by_timer_pattern)) { 1175 wma_debug("TIME_PATTERN is not enabled"); 1176 return; 1177 } 1178 1179 for (i = 0; i < wma->max_bssid; i++) { 1180 iface = &wma->interfaces[i]; 1181 if (iface->vdev_active && iface->is_waiting_for_key) { 1182 /* 1183 * right now cookie is dont care, since FW disregards 1184 * that. 1185 */ 1186 is_set_key_in_progress = true; 1187 wma_wow_set_wake_time((WMA_HANDLE)wma, i, 0, time); 1188 break; 1189 } 1190 } 1191 1192 if (!is_set_key_in_progress) 1193 wma_debug("set key not in progress for any vdev"); 1194 } 1195 1196 /** 1197 * wma_unified_csa_offload_enable() - sen CSA offload enable command 1198 * @wma: wma handle 1199 * @vdev_id: vdev id 1200 * 1201 * Return: 0 for success or error code 1202 */ wma_unified_csa_offload_enable(tp_wma_handle wma,uint8_t vdev_id)1203 int wma_unified_csa_offload_enable(tp_wma_handle wma, uint8_t vdev_id) 1204 { 1205 if (wmi_unified_csa_offload_enable(wma->wmi_handle, 1206 vdev_id)) { 1207 wma_alert("Failed to send CSA offload enable command"); 1208 return -EIO; 1209 } 1210 1211 return 0; 1212 } 1213 #endif /* WLAN_POWER_MANAGEMENT_OFFLOAD */ 1214 1215 static uint8_t * wma_parse_ch_switch_wrapper_ie(uint8_t * ch_wr_ie,uint8_t sub_ele_id,uint8_t ie_extn_id)1216 wma_parse_ch_switch_wrapper_ie(uint8_t *ch_wr_ie, uint8_t sub_ele_id, 1217 uint8_t ie_extn_id) 1218 { 1219 uint8_t len = 0, sub_ele_len = 0; 1220 struct ie_header *ele; 1221 struct extn_ie_header *extn_ie; 1222 1223 ele = (struct ie_header *)ch_wr_ie; 1224 if (ele->ie_id != WLAN_ELEMID_CHAN_SWITCH_WRAP || ele->ie_len == 0) { 1225 wma_debug("Invalid len: %d", ele->ie_len); 1226 return NULL; 1227 } 1228 1229 len = ele->ie_len; 1230 ele = (struct ie_header *)(ch_wr_ie + sizeof(struct ie_header)); 1231 1232 while (len > 0) { 1233 sub_ele_len = sizeof(struct ie_header) + ele->ie_len; 1234 if (sub_ele_len > len) { 1235 wma_debug("invalid sub element len :%d id:%d ie len:%d", 1236 sub_ele_len, ele->ie_id, ele->ie_len); 1237 return NULL; 1238 } 1239 len -= sub_ele_len; 1240 if (ele->ie_id == sub_ele_id) { 1241 if (sub_ele_id == WLAN_ELEMID_EXTN_ELEM) { 1242 extn_ie = (struct extn_ie_header *)ele; 1243 if (extn_ie->ie_extn_id == ie_extn_id) 1244 return (uint8_t *)ele; 1245 } else { 1246 return (uint8_t *)ele; 1247 } 1248 } 1249 ele = (struct ie_header *)((uint8_t *)ele + sub_ele_len); 1250 } 1251 1252 return NULL; 1253 } 1254 1255 #ifdef WLAN_FEATURE_11BE 1256 /** 1257 * wma_parse_bw_indication_ie(): STA parse bandwidth indication IE of connected 1258 * AP for channel switch or puncture update. 1259 * @ie: bandwidth indication IE 1260 * @tlv_len: total length of ie tlv 1261 * @csa_event: struct to save channel switch info 1262 * 1263 * Return - QDF_STATUS. 1264 */ 1265 static wma_parse_bw_indication_ie(uint8_t * ie,uint8_t tlv_len,struct csa_offload_params * csa_event)1266 QDF_STATUS wma_parse_bw_indication_ie(uint8_t *ie, 1267 uint8_t tlv_len, 1268 struct csa_offload_params *csa_event) 1269 { 1270 uint16_t puncture_bitmap = 0; 1271 uint8_t *sub_ie; 1272 struct wlan_ie_bw_ind *bw_ind; 1273 struct ie_header *ie_head; 1274 uint8_t ccfs0, ccfs1; 1275 enum phy_ch_width ch_width; 1276 QDF_STATUS status; 1277 1278 ie_head = (struct ie_header *)ie; 1279 if (ie_head->ie_len + sizeof(struct ie_header) > tlv_len) { 1280 wma_err("Invalid ie len: %d, buffer len: %d", 1281 ie_head->ie_len, tlv_len); 1282 return QDF_STATUS_E_INVAL; 1283 } 1284 qdf_trace_hex_dump(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_DEBUG, 1285 ie, tlv_len); 1286 1287 sub_ie = wma_parse_ch_switch_wrapper_ie(ie, 1288 WLAN_ELEMID_EXTN_ELEM, 1289 WLAN_EXTN_ELEMID_BW_IND); 1290 if (!sub_ie) { 1291 wma_err("Invalid ie"); 1292 return QDF_STATUS_E_INVAL; 1293 } 1294 1295 bw_ind = (struct wlan_ie_bw_ind *)sub_ie; 1296 1297 status = util_parse_bw_ind(bw_ind, &ccfs0, &ccfs1, &ch_width, 1298 &puncture_bitmap); 1299 1300 wma_debug("ch width: %d, ccfs0: %d, ccfs1: %d, puncture: %d", ch_width, 1301 ccfs0, ccfs1, puncture_bitmap); 1302 1303 csa_event->new_ch_width = ch_width; 1304 csa_event->new_ch_freq_seg1 = ccfs0; 1305 csa_event->new_ch_freq_seg2 = ccfs1; 1306 csa_event->new_punct_bitmap = puncture_bitmap; 1307 1308 return QDF_STATUS_SUCCESS; 1309 } 1310 #else 1311 static inline wma_parse_bw_indication_ie(uint8_t * ie,uint8_t tlv_len,struct csa_offload_params * csa_event)1312 QDF_STATUS wma_parse_bw_indication_ie(uint8_t *ie, 1313 uint8_t tlv_len, 1314 struct csa_offload_params *csa_event) 1315 { 1316 return QDF_STATUS_E_NOSUPPORT; 1317 } 1318 #endif 1319 fill_csa_offload_params(wmi_csa_event_fixed_param * csa_event,struct csa_offload_params * csa_offload_event,struct wlan_objmgr_pdev * pdev)1320 static bool fill_csa_offload_params( 1321 wmi_csa_event_fixed_param *csa_event, 1322 struct csa_offload_params *csa_offload_event, 1323 struct wlan_objmgr_pdev *pdev) 1324 { 1325 struct ieee80211_channelswitch_ie *csa_ie; 1326 struct ieee80211_extendedchannelswitch_ie *xcsa_ie; 1327 uint8_t is_csa_ie_present = false; 1328 1329 if (csa_event->ies_present_flag & WMI_CSA_IE_PRESENT) { 1330 csa_ie = (struct ieee80211_channelswitch_ie *) 1331 (&csa_event->csa_ie[0]); 1332 csa_offload_event->channel = csa_ie->newchannel; 1333 csa_offload_event->csa_chan_freq = 1334 wlan_reg_legacy_chan_to_freq(pdev, 1335 csa_ie->newchannel); 1336 csa_offload_event->switch_mode = csa_ie->switchmode; 1337 csa_offload_event->ies_present_flag |= MLME_CSA_IE_PRESENT; 1338 is_csa_ie_present = true; 1339 } else if (csa_event->ies_present_flag & WMI_XCSA_IE_PRESENT) { 1340 xcsa_ie = (struct ieee80211_extendedchannelswitch_ie *) 1341 (&csa_event->xcsa_ie[0]); 1342 csa_offload_event->channel = xcsa_ie->newchannel; 1343 csa_offload_event->switch_mode = xcsa_ie->switchmode; 1344 csa_offload_event->new_op_class = xcsa_ie->newClass; 1345 if (wlan_reg_is_6ghz_op_class(pdev, xcsa_ie->newClass)) { 1346 csa_offload_event->csa_chan_freq = 1347 wlan_reg_chan_band_to_freq 1348 (pdev, xcsa_ie->newchannel, 1349 BIT(REG_BAND_6G)); 1350 } else { 1351 csa_offload_event->csa_chan_freq = 1352 wlan_reg_legacy_chan_to_freq 1353 (pdev, xcsa_ie->newchannel); 1354 } 1355 csa_offload_event->ies_present_flag |= MLME_XCSA_IE_PRESENT; 1356 is_csa_ie_present = true; 1357 } 1358 return is_csa_ie_present; 1359 } 1360 1361 #ifdef WLAN_FEATURE_11BE handle_csa_standby_link(wmi_csa_event_fixed_param * csa_event,struct wlan_objmgr_psoc * psoc,struct wlan_objmgr_pdev * pdev)1362 static bool handle_csa_standby_link(wmi_csa_event_fixed_param *csa_event, 1363 struct wlan_objmgr_psoc *psoc, 1364 struct wlan_objmgr_pdev *pdev) 1365 { 1366 struct mlo_link_info *link_info; 1367 struct wlan_mlo_dev_context *mldev; 1368 uint8_t mld_addr[QDF_MAC_ADDR_SIZE]; 1369 struct csa_offload_params csa_param = {0}; 1370 struct mlo_link_bss_params params = {0}; 1371 uint8_t is_csa_standby = false; 1372 uint8_t link_id; 1373 struct wlan_lmac_if_mlo_tx_ops *mlo_tx_ops; 1374 QDF_STATUS status = QDF_STATUS_SUCCESS; 1375 1376 if (!psoc) { 1377 wma_err("null psoc"); 1378 return is_csa_standby; 1379 } 1380 1381 WMI_MAC_ADDR_TO_CHAR_ARRAY(&csa_event->mld_mac_address, 1382 &mld_addr[0]); 1383 wlan_mlo_get_mlpeer_by_peer_mladdr( 1384 (struct qdf_mac_addr *)&mld_addr[0], 1385 &mldev); 1386 if (!mldev) { 1387 wma_err("NULL ml dev ctx"); 1388 return is_csa_standby; 1389 } 1390 1391 link_id = csa_event->link_id; 1392 link_info = mlo_mgr_get_ap_link_by_link_id(mldev, 1393 link_id); 1394 if (!link_info) { 1395 wma_err("NULL link info "); 1396 return is_csa_standby; 1397 } 1398 1399 if (link_info->vdev_id != WLAN_INVALID_VDEV_ID) { 1400 wma_debug("vdev id %d link id %d ", link_info->vdev_id, 1401 link_id); 1402 return is_csa_standby; 1403 } 1404 1405 mlo_tx_ops = &psoc->soc_cb.tx_ops->mlo_ops; 1406 if (!mlo_tx_ops) { 1407 wma_err("tx_ops is null!"); 1408 return is_csa_standby; 1409 } 1410 1411 if (!fill_csa_offload_params(csa_event, &csa_param, pdev)) { 1412 wma_err("CSA Event error: No CSA IE present"); 1413 return is_csa_standby; 1414 } 1415 1416 mlo_mgr_update_csa_link_info(pdev, mldev, &csa_param, link_id); 1417 1418 params.link_id = link_info->link_id; 1419 params.chan = qdf_mem_malloc(sizeof(struct wlan_channel)); 1420 if (!params.chan) { 1421 wma_err("no mem acquired"); 1422 return is_csa_standby; 1423 } 1424 1425 qdf_copy_macaddr((struct qdf_mac_addr *)¶ms.ap_mld_mac[0], 1426 &link_info->ap_link_addr); 1427 1428 params.chan->ch_freq = link_info->link_chan_info->ch_freq; 1429 params.chan->ch_cfreq1 = link_info->link_chan_info->ch_cfreq1; 1430 params.chan->ch_cfreq2 = link_info->link_chan_info->ch_cfreq2; 1431 params.chan->ch_phymode = link_info->link_chan_info->ch_phymode; 1432 1433 mlo_debug("link id %d chan freq %d cfreq1 %d cfreq2 %d host phymode %d ap mld mac " QDF_MAC_ADDR_FMT, 1434 link_info->link_id, link_info->link_chan_info->ch_freq, 1435 link_info->link_chan_info->ch_cfreq1, 1436 link_info->link_chan_info->ch_cfreq2, 1437 link_info->link_chan_info->ch_phymode, 1438 QDF_MAC_ADDR_REF(¶ms.ap_mld_mac[0])); 1439 1440 if (!mlo_tx_ops->send_link_set_bss_params_cmd) { 1441 wma_err("handler is not registered"); 1442 qdf_mem_free(params.chan); 1443 return is_csa_standby; 1444 } 1445 1446 status = mlo_tx_ops->send_link_set_bss_params_cmd(psoc, ¶ms); 1447 1448 if (QDF_IS_STATUS_ERROR(status)) { 1449 wma_err("failed to send link set bss request command to FW"); 1450 qdf_mem_free(params.chan); 1451 return is_csa_standby; 1452 } 1453 1454 is_csa_standby = true; 1455 qdf_mem_free(params.chan); 1456 1457 return is_csa_standby; 1458 } 1459 fill_peer_mac_addr(wmi_csa_event_fixed_param * csa_event,uint8_t * bssid)1460 static int fill_peer_mac_addr(wmi_csa_event_fixed_param *csa_event, 1461 uint8_t *bssid) 1462 { 1463 QDF_STATUS status = QDF_STATUS_SUCCESS; 1464 uint8_t mld_addr[QDF_MAC_ADDR_SIZE]; 1465 uint8_t link_addr[QDF_MAC_ADDR_SIZE]; 1466 uint8_t link_id; 1467 struct mlo_link_info *link_info; 1468 struct wlan_mlo_dev_context *mldev; 1469 1470 WMI_MAC_ADDR_TO_CHAR_ARRAY(&csa_event->mld_mac_address, 1471 &mld_addr[0]); 1472 WMI_MAC_ADDR_TO_CHAR_ARRAY(&csa_event->link_mac_address, 1473 &link_addr[0]); 1474 wlan_mlo_get_mlpeer_by_peer_mladdr( 1475 (struct qdf_mac_addr *)&mld_addr[0], 1476 &mldev); 1477 if (!mldev) { 1478 wma_err("NULL ml dev ctx"); 1479 return -EINVAL; 1480 } 1481 1482 link_id = csa_event->link_id; 1483 link_info = mlo_mgr_get_ap_link_by_link_id(mldev, 1484 link_id); 1485 if (!link_info) { 1486 wma_err("NULL link info "); 1487 return -EINVAL; 1488 } 1489 1490 qdf_copy_macaddr((struct qdf_mac_addr *)&bssid[0], 1491 &link_info->ap_link_addr); 1492 wma_debug("csa event link id %d vdev id %d peer mld addr" QDF_MAC_ADDR_FMT "peer link addr" QDF_MAC_ADDR_FMT "host link info ap_link_addr" QDF_MAC_ADDR_FMT, 1493 link_id, link_info->vdev_id, 1494 QDF_MAC_ADDR_REF(&mld_addr[0]), 1495 QDF_MAC_ADDR_REF(&link_addr[0]), 1496 QDF_MAC_ADDR_REF(link_info->ap_link_addr.bytes)); 1497 1498 return status; 1499 } 1500 1501 #else fill_peer_mac_addr(wmi_csa_event_fixed_param * csa_event,uint8_t * bssid)1502 static int fill_peer_mac_addr(wmi_csa_event_fixed_param *csa_event, 1503 uint8_t *bssid) 1504 { 1505 return 0; 1506 } 1507 handle_csa_standby_link(wmi_csa_event_fixed_param * csa_event,struct wlan_objmgr_psoc * psoc,struct wlan_objmgr_pdev * pdev)1508 static bool handle_csa_standby_link(wmi_csa_event_fixed_param *csa_event, 1509 struct wlan_objmgr_psoc *psoc, 1510 struct wlan_objmgr_pdev *pdev) 1511 { 1512 return false; 1513 } 1514 1515 #endif 1516 1517 /** 1518 * wma_csa_offload_handler() - CSA event handler 1519 * @handle: wma handle 1520 * @event: event buffer 1521 * @len: buffer length 1522 * 1523 * This event is sent by firmware when it receives CSA IE. 1524 * 1525 * Return: 0 for success or error code 1526 */ wma_csa_offload_handler(void * handle,uint8_t * event,uint32_t len)1527 int wma_csa_offload_handler(void *handle, uint8_t *event, uint32_t len) 1528 { 1529 tp_wma_handle wma = (tp_wma_handle) handle; 1530 WMI_CSA_HANDLING_EVENTID_param_tlvs *param_buf; 1531 wmi_csa_event_fixed_param *csa_event; 1532 uint8_t bssid[QDF_MAC_ADDR_SIZE]; 1533 uint8_t vdev_id = 0; 1534 uint8_t cur_chan = 0; 1535 struct csa_offload_params *csa_offload_event; 1536 struct ieee80211_ie_wide_bw_switch *wb_ie; 1537 struct wlan_objmgr_peer *peer; 1538 struct wlan_objmgr_vdev *vdev; 1539 QDF_STATUS status; 1540 uint8_t tlv_len; 1541 struct wlan_channel *chan; 1542 1543 param_buf = (WMI_CSA_HANDLING_EVENTID_param_tlvs *) event; 1544 1545 wma_debug("Enter"); 1546 if (!param_buf) { 1547 wma_err("Invalid csa event buffer"); 1548 return -EINVAL; 1549 } 1550 csa_event = param_buf->fixed_param; 1551 1552 if (csa_event->link_id_present && 1553 csa_event->mld_mac_address_present) { 1554 status = fill_peer_mac_addr(csa_event, &bssid[0]); 1555 if (status) 1556 return -EINVAL; 1557 1558 /* check standby link and return */ 1559 if (handle_csa_standby_link(csa_event, wma->psoc, wma->pdev)) 1560 return 0; 1561 } else { 1562 WMI_MAC_ADDR_TO_CHAR_ARRAY(&csa_event->i_addr2, 1563 &bssid[0]); 1564 } 1565 1566 peer = wlan_objmgr_get_peer_by_mac(wma->psoc, 1567 bssid, WLAN_LEGACY_WMA_ID); 1568 if (!peer) { 1569 wma_err("Invalid peer"); 1570 return -EINVAL; 1571 } 1572 1573 vdev_id = wlan_vdev_get_id(wlan_peer_get_vdev(peer)); 1574 wlan_objmgr_peer_release_ref(peer, WLAN_LEGACY_WMA_ID); 1575 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(wma->psoc, 1576 vdev_id, 1577 WLAN_LEGACY_WMA_ID); 1578 if (!vdev) 1579 return -EINVAL; 1580 1581 csa_offload_event = qdf_mem_malloc(sizeof(*csa_offload_event)); 1582 if (!csa_offload_event) { 1583 wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_WMA_ID); 1584 return -EINVAL; 1585 } 1586 if (wlan_cm_is_vdev_roaming(vdev)) { 1587 wma_err("Roaming in progress for vdev %d, ignore csa event", 1588 vdev_id); 1589 qdf_mem_free(csa_offload_event); 1590 wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_WMA_ID); 1591 return -EINVAL; 1592 } 1593 1594 qdf_mem_zero(csa_offload_event, sizeof(*csa_offload_event)); 1595 qdf_copy_macaddr(&csa_offload_event->bssid, 1596 (struct qdf_mac_addr *)bssid); 1597 1598 if (!fill_csa_offload_params(csa_event, csa_offload_event, wma->pdev)) { 1599 wma_err("CSA Event error: No CSA IE present"); 1600 qdf_mem_free(csa_offload_event); 1601 wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_WMA_ID); 1602 return -EINVAL; 1603 } 1604 1605 if (csa_event->ies_present_flag & WMI_CSWRAP_IE_EXT_VER_2_PRESENT) { 1606 wma_debug("WMI_CSWRAP_IE_EXT_VER_2 received"); 1607 tlv_len = csa_event->num_bytes_valid_in_cswrap_ie_ext_ver2; 1608 status = wma_parse_bw_indication_ie(param_buf->cs_wrap_ie, 1609 tlv_len, 1610 csa_offload_event); 1611 if (QDF_IS_STATUS_SUCCESS(status)) { 1612 csa_offload_event->ies_present_flag |= 1613 MLME_CSWRAP_IE_EXT_V2_PRESENT; 1614 goto got_chan; 1615 } 1616 } 1617 1618 if (csa_event->ies_present_flag & WMI_WBW_IE_PRESENT) { 1619 wb_ie = (struct ieee80211_ie_wide_bw_switch *) 1620 (&csa_event->wb_ie[0]); 1621 csa_offload_event->new_ch_freq_seg1 = wb_ie->new_ch_freq_seg1; 1622 csa_offload_event->new_ch_freq_seg2 = wb_ie->new_ch_freq_seg2; 1623 csa_offload_event->new_ch_width = 1624 wlan_mlme_convert_vht_op_bw_to_phy_ch_width(wb_ie->new_ch_width, 1625 csa_offload_event->channel, 1626 wb_ie->new_ch_freq_seg1, 1627 wb_ie->new_ch_freq_seg2); 1628 1629 csa_offload_event->ies_present_flag |= MLME_WBW_IE_PRESENT; 1630 } else if (csa_event->ies_present_flag & 1631 WMI_CSWRAP_IE_EXTENDED_PRESENT) { 1632 wb_ie = (struct ieee80211_ie_wide_bw_switch *) 1633 wma_parse_ch_switch_wrapper_ie( 1634 (uint8_t *)&csa_event->cswrap_ie_extended, 1635 WLAN_ELEMID_WIDE_BAND_CHAN_SWITCH, 0); 1636 if (wb_ie) { 1637 csa_offload_event->new_ch_freq_seg1 = 1638 wb_ie->new_ch_freq_seg1; 1639 csa_offload_event->new_ch_freq_seg2 = 1640 wb_ie->new_ch_freq_seg2; 1641 csa_offload_event->new_ch_width = 1642 wlan_mlme_convert_vht_op_bw_to_phy_ch_width(wb_ie->new_ch_width, 1643 csa_offload_event->channel, 1644 wb_ie->new_ch_freq_seg1, 1645 wb_ie->new_ch_freq_seg2); 1646 csa_event->ies_present_flag |= WMI_WBW_IE_PRESENT; 1647 csa_offload_event->ies_present_flag |= 1648 MLME_WBW_IE_PRESENT; 1649 } 1650 csa_offload_event->ies_present_flag |= 1651 MLME_CSWRAP_IE_EXTENDED_PRESENT; 1652 } 1653 1654 got_chan: 1655 wma_debug("CSA: BSSID "QDF_MAC_ADDR_FMT" chan %d freq %d flag 0x%x width = %d freq1 = %d freq2 = %d op class = %d", 1656 QDF_MAC_ADDR_REF(csa_offload_event->bssid.bytes), 1657 csa_offload_event->channel, 1658 csa_offload_event->csa_chan_freq, 1659 csa_offload_event->ies_present_flag, 1660 csa_offload_event->new_ch_width, 1661 csa_offload_event->new_ch_freq_seg1, 1662 csa_offload_event->new_ch_freq_seg2, 1663 csa_offload_event->new_op_class); 1664 1665 chan = wlan_vdev_get_active_channel(vdev); 1666 if (!chan) { 1667 wmi_err("failed to get active channel"); 1668 wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_WMA_ID); 1669 qdf_mem_free(csa_offload_event); 1670 return false; 1671 } 1672 wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_WMA_ID); 1673 cur_chan = cds_freq_to_chan(chan->ch_freq); 1674 /* 1675 * basic sanity check: requested channel should not be 0 1676 * and equal to home channel 1677 */ 1678 if (0 == csa_offload_event->channel) { 1679 wma_err("CSA Event with channel %d. Ignore !!", 1680 csa_offload_event->channel); 1681 qdf_mem_free(csa_offload_event); 1682 return -EINVAL; 1683 } 1684 1685 wma_send_msg(wma, WMA_CSA_OFFLOAD_EVENT, (void *)csa_offload_event, 0); 1686 return 0; 1687 } 1688 1689 #ifdef FEATURE_OEM_DATA_SUPPORT 1690 /** 1691 * wma_oem_data_response_handler() - OEM data response event handler 1692 * @handle: wma handle 1693 * @datap: data ptr 1694 * @len: data length 1695 * 1696 * Return: 0 for success or error code 1697 */ wma_oem_data_response_handler(void * handle,uint8_t * datap,uint32_t len)1698 int wma_oem_data_response_handler(void *handle, 1699 uint8_t *datap, uint32_t len) 1700 { 1701 WMI_OEM_RESPONSE_EVENTID_param_tlvs *param_buf; 1702 uint8_t *data; 1703 uint32_t datalen; 1704 struct oem_data_rsp *oem_rsp; 1705 struct mac_context *pmac = cds_get_context(QDF_MODULE_ID_PE); 1706 1707 if (!pmac) 1708 return -EINVAL; 1709 1710 if (!pmac->sme.oem_data_rsp_callback) { 1711 wma_err("Callback not registered"); 1712 return -EINVAL; 1713 } 1714 1715 param_buf = (WMI_OEM_RESPONSE_EVENTID_param_tlvs *) datap; 1716 if (!param_buf) { 1717 wma_err("Received NULL buf ptr from FW"); 1718 return -ENOMEM; 1719 } 1720 1721 data = param_buf->data; 1722 datalen = param_buf->num_data; 1723 1724 if (!data) { 1725 wma_err("Received NULL data from FW"); 1726 return -EINVAL; 1727 } 1728 1729 if (datalen > OEM_DATA_RSP_SIZE) { 1730 wma_err("Received data len %d exceeds max value %d", 1731 datalen, OEM_DATA_RSP_SIZE); 1732 return -EINVAL; 1733 } 1734 1735 oem_rsp = qdf_mem_malloc(sizeof(*oem_rsp)); 1736 if (!oem_rsp) 1737 return -ENOMEM; 1738 1739 oem_rsp->rsp_len = datalen; 1740 if (oem_rsp->rsp_len) { 1741 oem_rsp->data = qdf_mem_malloc(oem_rsp->rsp_len); 1742 if (!oem_rsp->data) { 1743 qdf_mem_free(oem_rsp); 1744 return -ENOMEM; 1745 } 1746 } else { 1747 wma_err("Invalid rsp length: %d", oem_rsp->rsp_len); 1748 qdf_mem_free(oem_rsp); 1749 return -EINVAL; 1750 } 1751 1752 qdf_mem_copy(oem_rsp->data, data, datalen); 1753 1754 wma_debug("Sending OEM_DATA_RSP(len: %d) to upper layer", datalen); 1755 1756 pmac->sme.oem_data_rsp_callback(oem_rsp); 1757 1758 if (oem_rsp->data) 1759 qdf_mem_free(oem_rsp->data); 1760 qdf_mem_free(oem_rsp); 1761 1762 return 0; 1763 } 1764 wma_start_oem_req_cmd(tp_wma_handle wma_handle,struct oem_data_req * oem_data_req)1765 QDF_STATUS wma_start_oem_req_cmd(tp_wma_handle wma_handle, 1766 struct oem_data_req *oem_data_req) 1767 { 1768 QDF_STATUS ret; 1769 struct wmi_unified *wmi_handle; 1770 1771 wma_debug("Send OEM Data Request to target"); 1772 1773 if (!oem_data_req || !oem_data_req->data) { 1774 wma_err("oem_data_req is null"); 1775 return QDF_STATUS_E_INVAL; 1776 } 1777 1778 if (wma_validate_handle(wma_handle)) { 1779 qdf_mem_free(oem_data_req->data); 1780 return QDF_STATUS_E_INVAL; 1781 } 1782 1783 wmi_handle = wma_handle->wmi_handle; 1784 if (wmi_validate_handle(wmi_handle)) { 1785 qdf_mem_free(oem_data_req->data); 1786 return QDF_STATUS_E_INVAL; 1787 } 1788 1789 /* legacy api, for oem data request case */ 1790 ret = wmi_unified_start_oem_data_cmd(wmi_handle, 1791 oem_data_req->data_len, 1792 oem_data_req->data); 1793 1794 if (!QDF_IS_STATUS_SUCCESS(ret)) 1795 wma_err("wmi cmd send failed"); 1796 1797 return ret; 1798 } 1799 #endif /* FEATURE_OEM_DATA_SUPPORT */ 1800 1801 #ifdef FEATURE_OEM_DATA wma_start_oem_data_cmd(tp_wma_handle wma_handle,struct oem_data * oem_data)1802 QDF_STATUS wma_start_oem_data_cmd(tp_wma_handle wma_handle, 1803 struct oem_data *oem_data) 1804 { 1805 QDF_STATUS ret; 1806 struct wmi_unified *wmi_handle; 1807 1808 wma_debug("Send OEM Data to target"); 1809 1810 if (!oem_data || !oem_data->data) { 1811 wma_err("oem_data is null"); 1812 return QDF_STATUS_E_INVAL; 1813 } 1814 1815 if (wma_validate_handle(wma_handle)) 1816 return QDF_STATUS_E_INVAL; 1817 1818 wmi_handle = wma_handle->wmi_handle; 1819 if (wmi_validate_handle(wmi_handle)) 1820 return QDF_STATUS_E_INVAL; 1821 1822 /* common api, for oem data command case */ 1823 ret = wmi_unified_start_oemv2_data_cmd(wmi_handle, oem_data); 1824 if (!QDF_IS_STATUS_SUCCESS(ret)) 1825 wma_err("call start wmi cmd failed"); 1826 1827 return ret; 1828 } 1829 #endif 1830 1831 #if !defined(REMOVE_PKT_LOG) && defined(FEATURE_PKTLOG) 1832 /** 1833 * wma_pktlog_wmi_send_cmd() - send pktlog enable/disable command to target 1834 * @handle: wma handle 1835 * @params: pktlog params 1836 * 1837 * Return: QDF status 1838 */ wma_pktlog_wmi_send_cmd(WMA_HANDLE handle,struct ath_pktlog_wmi_params * params)1839 QDF_STATUS wma_pktlog_wmi_send_cmd(WMA_HANDLE handle, 1840 struct ath_pktlog_wmi_params *params) 1841 { 1842 tp_wma_handle wma_handle = (tp_wma_handle) handle; 1843 int ret; 1844 1845 ret = wmi_unified_pktlog_wmi_send_cmd(wma_handle->wmi_handle, 1846 params->pktlog_event, 1847 params->cmd_id, params->user_triggered); 1848 if (ret) 1849 return QDF_STATUS_E_FAILURE; 1850 1851 return QDF_STATUS_SUCCESS; 1852 } 1853 #endif /* !REMOVE_PKT_LOG && FEATURE_PKTLOG */ 1854 1855 /** 1856 * wma_wow_wake_reason_str() - Converts wow wakeup reason code to text format 1857 * @wake_reason - WOW wake reason 1858 * 1859 * Return: reason code in string format 1860 */ wma_wow_wake_reason_str(A_INT32 wake_reason)1861 static const uint8_t *wma_wow_wake_reason_str(A_INT32 wake_reason) 1862 { 1863 switch (wake_reason) { 1864 case WOW_REASON_UNSPECIFIED: 1865 return "UNSPECIFIED"; 1866 case WOW_REASON_NLOD: 1867 return "NLOD"; 1868 case WOW_REASON_AP_ASSOC_LOST: 1869 return "AP_ASSOC_LOST"; 1870 case WOW_REASON_LOW_RSSI: 1871 return "LOW_RSSI"; 1872 case WOW_REASON_DEAUTH_RECVD: 1873 return "DEAUTH_RECVD"; 1874 case WOW_REASON_DISASSOC_RECVD: 1875 return "DISASSOC_RECVD"; 1876 case WOW_REASON_GTK_HS_ERR: 1877 return "GTK_HS_ERR"; 1878 case WOW_REASON_EAP_REQ: 1879 return "EAP_REQ"; 1880 case WOW_REASON_FOURWAY_HS_RECV: 1881 return "FOURWAY_HS_RECV"; 1882 case WOW_REASON_TIMER_INTR_RECV: 1883 return "TIMER_INTR_RECV"; 1884 case WOW_REASON_PATTERN_MATCH_FOUND: 1885 return "PATTERN_MATCH_FOUND"; 1886 case WOW_REASON_RECV_MAGIC_PATTERN: 1887 return "RECV_MAGIC_PATTERN"; 1888 case WOW_REASON_P2P_DISC: 1889 return "P2P_DISC"; 1890 case WOW_REASON_WLAN_HB: 1891 return "WLAN_HB"; 1892 case WOW_REASON_CSA_EVENT: 1893 return "CSA_EVENT"; 1894 case WOW_REASON_PROBE_REQ_WPS_IE_RECV: 1895 return "PROBE_REQ_WPS_IE_RECV"; 1896 case WOW_REASON_AUTH_REQ_RECV: 1897 return "AUTH_REQ_RECV"; 1898 case WOW_REASON_ASSOC_REQ_RECV: 1899 return "ASSOC_REQ_RECV"; 1900 case WOW_REASON_HTT_EVENT: 1901 return "HTT_EVENT"; 1902 case WOW_REASON_RA_MATCH: 1903 return "RA_MATCH"; 1904 case WOW_REASON_HOST_AUTO_SHUTDOWN: 1905 return "HOST_AUTO_SHUTDOWN"; 1906 case WOW_REASON_IOAC_MAGIC_EVENT: 1907 return "IOAC_MAGIC_EVENT"; 1908 case WOW_REASON_IOAC_SHORT_EVENT: 1909 return "IOAC_SHORT_EVENT"; 1910 case WOW_REASON_IOAC_EXTEND_EVENT: 1911 return "IOAC_EXTEND_EVENT"; 1912 case WOW_REASON_IOAC_TIMER_EVENT: 1913 return "IOAC_TIMER_EVENT"; 1914 case WOW_REASON_ROAM_HO: 1915 return "ROAM_HO"; 1916 case WOW_REASON_ROAM_PREAUTH_START: 1917 return "ROAM_PREAUTH_START_EVENT"; 1918 case WOW_REASON_DFS_PHYERR_RADADR_EVENT: 1919 return "DFS_PHYERR_RADADR_EVENT"; 1920 case WOW_REASON_BEACON_RECV: 1921 return "BEACON_RECV"; 1922 case WOW_REASON_CLIENT_KICKOUT_EVENT: 1923 return "CLIENT_KICKOUT_EVENT"; 1924 case WOW_REASON_NAN_EVENT: 1925 return "NAN_EVENT"; 1926 case WOW_REASON_EXTSCAN: 1927 return "EXTSCAN"; 1928 case WOW_REASON_RSSI_BREACH_EVENT: 1929 return "RSSI_BREACH_EVENT"; 1930 case WOW_REASON_IOAC_REV_KA_FAIL_EVENT: 1931 return "IOAC_REV_KA_FAIL_EVENT"; 1932 case WOW_REASON_IOAC_SOCK_EVENT: 1933 return "IOAC_SOCK_EVENT"; 1934 case WOW_REASON_NLO_SCAN_COMPLETE: 1935 return "NLO_SCAN_COMPLETE"; 1936 case WOW_REASON_PACKET_FILTER_MATCH: 1937 return "PACKET_FILTER_MATCH"; 1938 case WOW_REASON_ASSOC_RES_RECV: 1939 return "ASSOC_RES_RECV"; 1940 case WOW_REASON_REASSOC_REQ_RECV: 1941 return "REASSOC_REQ_RECV"; 1942 case WOW_REASON_REASSOC_RES_RECV: 1943 return "REASSOC_RES_RECV"; 1944 case WOW_REASON_ACTION_FRAME_RECV: 1945 return "ACTION_FRAME_RECV"; 1946 case WOW_REASON_BPF_ALLOW: 1947 return "BPF_ALLOW"; 1948 case WOW_REASON_NAN_DATA: 1949 return "NAN_DATA"; 1950 case WOW_REASON_OEM_RESPONSE_EVENT: 1951 return "OEM_RESPONSE_EVENT"; 1952 case WOW_REASON_TDLS_CONN_TRACKER_EVENT: 1953 return "TDLS_CONN_TRACKER_EVENT"; 1954 case WOW_REASON_CRITICAL_LOG: 1955 return "CRITICAL_LOG"; 1956 case WOW_REASON_P2P_LISTEN_OFFLOAD: 1957 return "P2P_LISTEN_OFFLOAD"; 1958 case WOW_REASON_NAN_EVENT_WAKE_HOST: 1959 return "NAN_EVENT_WAKE_HOST"; 1960 case WOW_REASON_DEBUG_TEST: 1961 return "DEBUG_TEST"; 1962 case WOW_REASON_CHIP_POWER_FAILURE_DETECT: 1963 return "CHIP_POWER_FAILURE_DETECT"; 1964 case WOW_REASON_11D_SCAN: 1965 return "11D_SCAN"; 1966 case WOW_REASON_SAP_OBSS_DETECTION: 1967 return "SAP_OBSS_DETECTION"; 1968 case WOW_REASON_BSS_COLOR_COLLISION_DETECT: 1969 return "BSS_COLOR_COLLISION_DETECT"; 1970 #ifdef WLAN_FEATURE_MOTION_DETECTION 1971 case WOW_REASON_WLAN_MD: 1972 return "MOTION_DETECT"; 1973 case WOW_REASON_WLAN_BL: 1974 return "MOTION_DETECT_BASELINE"; 1975 #endif /* WLAN_FEATURE_MOTION_DETECTION */ 1976 case WOW_REASON_PAGE_FAULT: 1977 return "PF"; 1978 case WOW_REASON_ROAM_PMKID_REQUEST: 1979 return "ROAM_PMKID_REQUEST"; 1980 case WOW_REASON_VDEV_DISCONNECT: 1981 return "VDEV_DISCONNECT"; 1982 case WOW_REASON_LOCAL_DATA_UC_DROP: 1983 return "LOCAL_DATA_UC_DROP"; 1984 case WOW_REASON_FATAL_EVENT_WAKE: 1985 return "FATAL_EVENT_WAKE"; 1986 case WOW_REASON_GENERIC_WAKE: 1987 return "GENERIC_WAKE"; 1988 case WOW_REASON_TWT: 1989 return "TWT Event"; 1990 case WOW_REASON_DCS_INT_DET: 1991 return "DCS_INT_DET"; 1992 case WOW_REASON_ROAM_STATS: 1993 return "ROAM_STATS"; 1994 case WOW_REASON_RTT_11AZ: 1995 return "WOW_REASON_RTT_11AZ"; 1996 case WOW_REASON_DELAYED_WAKEUP_HOST_CFG_TIMER_ELAPSED: 1997 return "DELAYED_WAKEUP_TIMER_ELAPSED"; 1998 case WOW_REASON_DELAYED_WAKEUP_DATA_STORE_LIST_FULL: 1999 return "DELAYED_WAKEUP_DATA_STORE_LIST_FULL"; 2000 #ifndef WLAN_SUPPORT_GAP_LL_PS_MODE 2001 case WOW_REASON_XGAP: 2002 return "XGAP"; 2003 #endif 2004 default: 2005 return "unknown"; 2006 } 2007 } 2008 wma_wow_reason_has_stats(enum wake_reason_e reason)2009 static bool wma_wow_reason_has_stats(enum wake_reason_e reason) 2010 { 2011 switch (reason) { 2012 case WOW_REASON_ASSOC_REQ_RECV: 2013 case WOW_REASON_DISASSOC_RECVD: 2014 case WOW_REASON_ASSOC_RES_RECV: 2015 case WOW_REASON_REASSOC_REQ_RECV: 2016 case WOW_REASON_REASSOC_RES_RECV: 2017 case WOW_REASON_AUTH_REQ_RECV: 2018 case WOW_REASON_DEAUTH_RECVD: 2019 case WOW_REASON_ACTION_FRAME_RECV: 2020 case WOW_REASON_BPF_ALLOW: 2021 case WOW_REASON_PATTERN_MATCH_FOUND: 2022 case WOW_REASON_PACKET_FILTER_MATCH: 2023 case WOW_REASON_RA_MATCH: 2024 case WOW_REASON_NLOD: 2025 case WOW_REASON_NLO_SCAN_COMPLETE: 2026 case WOW_REASON_LOW_RSSI: 2027 case WOW_REASON_EXTSCAN: 2028 case WOW_REASON_RSSI_BREACH_EVENT: 2029 case WOW_REASON_OEM_RESPONSE_EVENT: 2030 case WOW_REASON_CHIP_POWER_FAILURE_DETECT: 2031 case WOW_REASON_11D_SCAN: 2032 case WOW_REASON_LOCAL_DATA_UC_DROP: 2033 case WOW_REASON_FATAL_EVENT_WAKE: 2034 return true; 2035 #ifdef WLAN_FEATURE_MOTION_DETECTION 2036 case WOW_REASON_WLAN_MD: 2037 case WOW_REASON_WLAN_BL: 2038 return true; 2039 #endif /* WLAN_FEATURE_MOTION_DETECTION */ 2040 default: 2041 return false; 2042 } 2043 } 2044 wma_inc_wow_stats(t_wma_handle * wma,WOW_EVENT_INFO_fixed_param * wake_info)2045 static void wma_inc_wow_stats(t_wma_handle *wma, 2046 WOW_EVENT_INFO_fixed_param *wake_info) 2047 { 2048 ucfg_mc_cp_stats_inc_wake_lock_stats(wma->psoc, 2049 wake_info->vdev_id, 2050 wake_info->wake_reason); 2051 } 2052 wma_wow_stats_display(struct wake_lock_stats * stats)2053 static void wma_wow_stats_display(struct wake_lock_stats *stats) 2054 { 2055 wma_conditional_log(is_wakeup_event_console_logs_enabled, 2056 "WLAN wake reason counters:"); 2057 wma_conditional_log(is_wakeup_event_console_logs_enabled, 2058 "uc:%d bc:%d v4_mc:%d v6_mc:%d ra:%d ns:%d na:%d " 2059 "icmp:%d icmpv6:%d", 2060 stats->ucast_wake_up_count, 2061 stats->bcast_wake_up_count, 2062 stats->ipv4_mcast_wake_up_count, 2063 stats->ipv6_mcast_wake_up_count, 2064 stats->ipv6_mcast_ra_stats, 2065 stats->ipv6_mcast_ns_stats, 2066 stats->ipv6_mcast_na_stats, 2067 stats->icmpv4_count, 2068 stats->icmpv6_count); 2069 2070 wma_conditional_log(is_wakeup_event_console_logs_enabled, 2071 "assoc:%d disassoc:%d assoc_resp:%d reassoc:%d " 2072 "reassoc_resp:%d auth:%d deauth:%d action:%d", 2073 stats->mgmt_assoc, 2074 stats->mgmt_disassoc, 2075 stats->mgmt_assoc_resp, 2076 stats->mgmt_reassoc, 2077 stats->mgmt_reassoc_resp, 2078 stats->mgmt_auth, 2079 stats->mgmt_deauth, 2080 stats->mgmt_action); 2081 2082 wma_conditional_log(is_wakeup_event_console_logs_enabled, 2083 "pno_match:%d pno_complete:%d gscan:%d low_rssi:%d" 2084 " rssi_breach:%d oem:%d ucdrop:%d scan_11d:%d" 2085 " fatal_event:%d", 2086 stats->pno_match_wake_up_count, 2087 stats->pno_complete_wake_up_count, 2088 stats->gscan_wake_up_count, 2089 stats->low_rssi_wake_up_count, 2090 stats->rssi_breach_wake_up_count, 2091 stats->oem_response_wake_up_count, 2092 stats->uc_drop_wake_up_count, 2093 stats->scan_11d, 2094 stats->fatal_event_wake_up_count); 2095 } 2096 wma_print_wow_stats(t_wma_handle * wma,WOW_EVENT_INFO_fixed_param * wake_info)2097 static void wma_print_wow_stats(t_wma_handle *wma, 2098 WOW_EVENT_INFO_fixed_param *wake_info) 2099 { 2100 struct wlan_objmgr_vdev *vdev; 2101 struct wake_lock_stats stats = {0}; 2102 2103 if (!wma_wow_reason_has_stats(wake_info->wake_reason)) 2104 return; 2105 2106 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(wma->psoc, 2107 wake_info->vdev_id, 2108 WLAN_LEGACY_WMA_ID); 2109 if (!vdev) { 2110 wma_err("vdev_id: %d, failed to get vdev from psoc", 2111 wake_info->vdev_id); 2112 return; 2113 } 2114 2115 ucfg_mc_cp_stats_get_vdev_wake_lock_stats(vdev, &stats); 2116 wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_WMA_ID); 2117 wma_wow_stats_display(&stats); 2118 } 2119 2120 #ifdef FEATURE_WLAN_EXTSCAN 2121 /** 2122 * wma_extscan_get_eventid_from_tlvtag() - map tlv tag to corresponding event id 2123 * @tag: WMI TLV tag 2124 * 2125 * Return: 2126 * 0 if TLV tag is invalid 2127 * else return corresponding WMI event id 2128 */ wma_extscan_get_eventid_from_tlvtag(uint32_t tag)2129 static int wma_extscan_get_eventid_from_tlvtag(uint32_t tag) 2130 { 2131 uint32_t event_id; 2132 2133 switch (tag) { 2134 case WMITLV_TAG_STRUC_wmi_extscan_start_stop_event_fixed_param: 2135 event_id = WMI_EXTSCAN_START_STOP_EVENTID; 2136 break; 2137 2138 case WMITLV_TAG_STRUC_wmi_extscan_operation_event_fixed_param: 2139 event_id = WMI_EXTSCAN_OPERATION_EVENTID; 2140 break; 2141 2142 case WMITLV_TAG_STRUC_wmi_extscan_table_usage_event_fixed_param: 2143 event_id = WMI_EXTSCAN_TABLE_USAGE_EVENTID; 2144 break; 2145 2146 case WMITLV_TAG_STRUC_wmi_extscan_cached_results_event_fixed_param: 2147 event_id = WMI_EXTSCAN_CACHED_RESULTS_EVENTID; 2148 break; 2149 2150 case WMITLV_TAG_STRUC_wmi_extscan_wlan_change_results_event_fixed_param: 2151 event_id = WMI_EXTSCAN_WLAN_CHANGE_RESULTS_EVENTID; 2152 break; 2153 2154 case WMITLV_TAG_STRUC_wmi_extscan_hotlist_match_event_fixed_param: 2155 event_id = WMI_EXTSCAN_HOTLIST_MATCH_EVENTID; 2156 break; 2157 2158 case WMITLV_TAG_STRUC_wmi_extscan_capabilities_event_fixed_param: 2159 event_id = WMI_EXTSCAN_CAPABILITIES_EVENTID; 2160 break; 2161 2162 default: 2163 event_id = 0; 2164 wma_err("Unknown tag: %d", tag); 2165 break; 2166 } 2167 2168 wma_info("For tag %d WMI event 0x%x", tag, event_id); 2169 return event_id; 2170 } 2171 #else wma_extscan_get_eventid_from_tlvtag(uint32_t tag)2172 static int wma_extscan_get_eventid_from_tlvtag(uint32_t tag) 2173 { 2174 return 0; 2175 } 2176 #endif 2177 2178 /** 2179 * wow_get_wmi_eventid() - map reason or tlv tag to corresponding event id 2180 * @tag: WMI TLV tag 2181 * @reason: WOW reason 2182 * 2183 * WOW reason type is primarily used to find the ID. If there could be 2184 * multiple events that can be sent as a WOW event with same reason 2185 * then tlv tag is used to identify the corresponding event. 2186 * 2187 * Return: 2188 * 0 if TLV tag/reason is invalid 2189 * else return corresponding WMI event id 2190 */ wow_get_wmi_eventid(int32_t reason,uint32_t tag)2191 static int wow_get_wmi_eventid(int32_t reason, uint32_t tag) 2192 { 2193 int event_id; 2194 2195 switch (reason) { 2196 case WOW_REASON_AP_ASSOC_LOST: 2197 event_id = WMI_ROAM_EVENTID; 2198 break; 2199 case WOW_REASON_NLO_SCAN_COMPLETE: 2200 event_id = WMI_NLO_SCAN_COMPLETE_EVENTID; 2201 break; 2202 case WOW_REASON_CSA_EVENT: 2203 event_id = WMI_CSA_HANDLING_EVENTID; 2204 break; 2205 case WOW_REASON_LOW_RSSI: 2206 event_id = WMI_ROAM_EVENTID; 2207 break; 2208 case WOW_REASON_CLIENT_KICKOUT_EVENT: 2209 event_id = WMI_PEER_STA_KICKOUT_EVENTID; 2210 break; 2211 case WOW_REASON_EXTSCAN: 2212 event_id = wma_extscan_get_eventid_from_tlvtag(tag); 2213 break; 2214 case WOW_REASON_RSSI_BREACH_EVENT: 2215 event_id = WMI_RSSI_BREACH_EVENTID; 2216 break; 2217 case WOW_REASON_NAN_EVENT: 2218 event_id = WMI_NAN_EVENTID; 2219 break; 2220 case WOW_REASON_NAN_DATA: 2221 event_id = wma_ndp_get_eventid_from_tlvtag(tag); 2222 break; 2223 case WOW_REASON_TDLS_CONN_TRACKER_EVENT: 2224 event_id = WMI_TDLS_PEER_EVENTID; 2225 break; 2226 case WOW_REASON_ROAM_HO: 2227 event_id = WMI_ROAM_EVENTID; 2228 break; 2229 case WOW_REASON_11D_SCAN: 2230 event_id = WMI_11D_NEW_COUNTRY_EVENTID; 2231 break; 2232 case WOW_REASON_ROAM_PMKID_REQUEST: 2233 event_id = WMI_ROAM_PMKID_REQUEST_EVENTID; 2234 break; 2235 case WOW_REASON_VDEV_DISCONNECT: 2236 event_id = WMI_VDEV_DISCONNECT_EVENTID; 2237 break; 2238 default: 2239 wma_debug("No Event Id for WOW reason %s(%d)", 2240 wma_wow_wake_reason_str(reason), reason); 2241 event_id = 0; 2242 break; 2243 } 2244 wlan_roam_debug_log(WMA_INVALID_VDEV_ID, DEBUG_WOW_REASON, 2245 DEBUG_INVALID_PEER_ID, NULL, NULL, 2246 reason, event_id); 2247 2248 return event_id; 2249 } 2250 2251 /** 2252 * is_piggybacked_event() - Returns true if the given wake reason indicates 2253 * there will be piggybacked TLV event data 2254 * @reason: WOW reason 2255 * 2256 * There are three types of WoW event payloads: none, piggybacked event, and 2257 * network packet. This function returns true for wake reasons that fall into 2258 * the piggybacked event case. 2259 * 2260 * Return: true for piggybacked event data 2261 */ is_piggybacked_event(int32_t reason)2262 static bool is_piggybacked_event(int32_t reason) 2263 { 2264 switch (reason) { 2265 case WOW_REASON_AP_ASSOC_LOST: 2266 case WOW_REASON_NLO_SCAN_COMPLETE: 2267 case WOW_REASON_CSA_EVENT: 2268 case WOW_REASON_LOW_RSSI: 2269 case WOW_REASON_CLIENT_KICKOUT_EVENT: 2270 case WOW_REASON_EXTSCAN: 2271 case WOW_REASON_RSSI_BREACH_EVENT: 2272 case WOW_REASON_NAN_EVENT: 2273 case WOW_REASON_NAN_DATA: 2274 case WOW_REASON_TDLS_CONN_TRACKER_EVENT: 2275 case WOW_REASON_ROAM_HO: 2276 case WOW_REASON_ROAM_PMKID_REQUEST: 2277 case WOW_REASON_VDEV_DISCONNECT: 2278 case WOW_REASON_TWT: 2279 return true; 2280 default: 2281 return false; 2282 } 2283 } 2284 2285 /** 2286 * wma_pkt_proto_subtype_to_string() - to convert proto subtype 2287 * of data packet to string. 2288 * @proto_subtype: proto subtype for data packet 2289 * 2290 * This function returns the string for the proto subtype of 2291 * data packet. 2292 * 2293 * Return: string for proto subtype for data packet 2294 */ 2295 static const char * wma_pkt_proto_subtype_to_string(enum qdf_proto_subtype proto_subtype)2296 wma_pkt_proto_subtype_to_string(enum qdf_proto_subtype proto_subtype) 2297 { 2298 switch (proto_subtype) { 2299 case QDF_PROTO_EAPOL_M1: 2300 return "EAPOL M1"; 2301 case QDF_PROTO_EAPOL_M2: 2302 return "EAPOL M2"; 2303 case QDF_PROTO_EAPOL_M3: 2304 return "EAPOL M3"; 2305 case QDF_PROTO_EAPOL_M4: 2306 return "EAPOL M4"; 2307 case QDF_PROTO_DHCP_DISCOVER: 2308 return "DHCP DISCOVER"; 2309 case QDF_PROTO_DHCP_REQUEST: 2310 return "DHCP REQUEST"; 2311 case QDF_PROTO_DHCP_OFFER: 2312 return "DHCP OFFER"; 2313 case QDF_PROTO_DHCP_ACK: 2314 return "DHCP ACK"; 2315 case QDF_PROTO_DHCP_NACK: 2316 return "DHCP NACK"; 2317 case QDF_PROTO_DHCP_RELEASE: 2318 return "DHCP RELEASE"; 2319 case QDF_PROTO_DHCP_INFORM: 2320 return "DHCP INFORM"; 2321 case QDF_PROTO_DHCP_DECLINE: 2322 return "DHCP DECLINE"; 2323 case QDF_PROTO_ARP_REQ: 2324 return "ARP REQUEST"; 2325 case QDF_PROTO_ARP_RES: 2326 return "ARP RESPONSE"; 2327 case QDF_PROTO_ICMP_REQ: 2328 return "ICMP REQUEST"; 2329 case QDF_PROTO_ICMP_RES: 2330 return "ICMP RESPONSE"; 2331 case QDF_PROTO_ICMPV6_REQ: 2332 return "ICMPV6 REQUEST"; 2333 case QDF_PROTO_ICMPV6_RES: 2334 return "ICMPV6 RESPONSE"; 2335 case QDF_PROTO_ICMPV6_RS: 2336 return "ICMPV6 RS"; 2337 case QDF_PROTO_ICMPV6_RA: 2338 return "ICMPV6 RA"; 2339 case QDF_PROTO_ICMPV6_NS: 2340 return "ICMPV6 NS"; 2341 case QDF_PROTO_ICMPV6_NA: 2342 return "ICMPV6 NA"; 2343 case QDF_PROTO_IPV4_UDP: 2344 return "IPV4 UDP Packet"; 2345 case QDF_PROTO_IPV4_TCP: 2346 return "IPV4 TCP Packet"; 2347 case QDF_PROTO_IPV6_UDP: 2348 return "IPV6 UDP Packet"; 2349 case QDF_PROTO_IPV6_TCP: 2350 return "IPV6 TCP Packet"; 2351 default: 2352 return NULL; 2353 } 2354 } 2355 2356 /** 2357 * wma_wow_get_pkt_proto_subtype() - get the proto subtype of the packet. 2358 * @data: Pointer to the packet data buffer 2359 * @len: length of the packet data buffer 2360 * 2361 * Return: proto subtype of the packet. 2362 */ 2363 static enum qdf_proto_subtype wma_wow_get_pkt_proto_subtype(uint8_t * data,uint32_t len)2364 wma_wow_get_pkt_proto_subtype(uint8_t *data, uint32_t len) 2365 { 2366 uint16_t eth_type; 2367 uint8_t proto_type; 2368 2369 if (len < QDF_NBUF_TRAC_ETH_TYPE_OFFSET + 2) { 2370 wma_err("Malformed ethernet packet: length %u < %d", 2371 len, QDF_NBUF_TRAC_ETH_TYPE_OFFSET + 2); 2372 return QDF_PROTO_INVALID; 2373 } 2374 2375 eth_type = *(uint16_t *)(data + QDF_NBUF_TRAC_ETH_TYPE_OFFSET); 2376 eth_type = qdf_cpu_to_be16(eth_type); 2377 2378 wma_debug("Ether Type: 0x%04x", eth_type); 2379 switch (eth_type) { 2380 case QDF_NBUF_TRAC_EAPOL_ETH_TYPE: 2381 if (len < WMA_EAPOL_SUBTYPE_GET_MIN_LEN) 2382 return QDF_PROTO_INVALID; 2383 2384 wma_debug("EAPOL Packet"); 2385 return qdf_nbuf_data_get_eapol_subtype(data); 2386 2387 case QDF_NBUF_TRAC_ARP_ETH_TYPE: 2388 if (len < WMA_ARP_SUBTYPE_GET_MIN_LEN) 2389 return QDF_PROTO_INVALID; 2390 2391 wma_debug("ARP Packet"); 2392 return qdf_nbuf_data_get_arp_subtype(data); 2393 2394 case QDF_NBUF_TRAC_IPV4_ETH_TYPE: 2395 if (len < WMA_IPV4_PROTO_GET_MIN_LEN) 2396 return QDF_PROTO_INVALID; 2397 2398 wma_debug("IPV4 Packet"); 2399 2400 proto_type = qdf_nbuf_data_get_ipv4_proto(data); 2401 wma_debug("IPV4_proto_type: %u", proto_type); 2402 2403 switch (proto_type) { 2404 case QDF_NBUF_TRAC_ICMP_TYPE: 2405 if (len < WMA_ICMP_SUBTYPE_GET_MIN_LEN) 2406 return QDF_PROTO_INVALID; 2407 2408 wma_debug("ICMP Packet"); 2409 return qdf_nbuf_data_get_icmp_subtype(data); 2410 2411 case QDF_NBUF_TRAC_UDP_TYPE: 2412 if (len < WMA_IS_DHCP_GET_MIN_LEN) 2413 return QDF_PROTO_IPV4_UDP; 2414 2415 if (!qdf_nbuf_data_is_ipv4_dhcp_pkt(data)) 2416 return QDF_PROTO_IPV4_UDP; 2417 2418 if (len < WMA_DHCP_SUBTYPE_GET_MIN_LEN) 2419 return QDF_PROTO_INVALID; 2420 2421 wma_debug("DHCP Packet"); 2422 return qdf_nbuf_data_get_dhcp_subtype(data); 2423 2424 case QDF_NBUF_TRAC_TCP_TYPE: 2425 return QDF_PROTO_IPV4_TCP; 2426 2427 default: 2428 return QDF_PROTO_INVALID; 2429 } 2430 2431 case QDF_NBUF_TRAC_IPV6_ETH_TYPE: 2432 if (len < WMA_IPV6_PROTO_GET_MIN_LEN) 2433 return QDF_PROTO_INVALID; 2434 2435 wma_debug("IPV6 Packet"); 2436 2437 proto_type = qdf_nbuf_data_get_ipv6_proto(data); 2438 wma_debug("IPV6_proto_type: %u", proto_type); 2439 2440 switch (proto_type) { 2441 case QDF_NBUF_TRAC_ICMPV6_TYPE: 2442 if (len < WMA_ICMPV6_SUBTYPE_GET_MIN_LEN) 2443 return QDF_PROTO_INVALID; 2444 2445 wma_debug("ICMPV6 Packet"); 2446 return qdf_nbuf_data_get_icmpv6_subtype(data); 2447 2448 case QDF_NBUF_TRAC_UDP_TYPE: 2449 return QDF_PROTO_IPV6_UDP; 2450 2451 case QDF_NBUF_TRAC_TCP_TYPE: 2452 return QDF_PROTO_IPV6_TCP; 2453 2454 default: 2455 return QDF_PROTO_INVALID; 2456 } 2457 2458 default: 2459 return QDF_PROTO_INVALID; 2460 } 2461 } 2462 wma_log_pkt_eapol(uint8_t * data,uint32_t length)2463 static void wma_log_pkt_eapol(uint8_t *data, uint32_t length) 2464 { 2465 uint16_t pkt_len, key_len; 2466 2467 if (length < WMA_EAPOL_INFO_GET_MIN_LEN) 2468 return; 2469 2470 pkt_len = *(uint16_t *)(data + EAPOL_PKT_LEN_OFFSET); 2471 key_len = *(uint16_t *)(data + EAPOL_KEY_LEN_OFFSET); 2472 wma_debug("Pkt_len: %u, Key_len: %u", 2473 qdf_cpu_to_be16(pkt_len), qdf_cpu_to_be16(key_len)); 2474 } 2475 wma_log_pkt_dhcp(uint8_t * data,uint32_t length)2476 static void wma_log_pkt_dhcp(uint8_t *data, uint32_t length) 2477 { 2478 uint16_t pkt_len; 2479 uint32_t trans_id; 2480 2481 if (length < WMA_DHCP_INFO_GET_MIN_LEN) 2482 return; 2483 2484 pkt_len = *(uint16_t *)(data + DHCP_PKT_LEN_OFFSET); 2485 trans_id = *(uint32_t *)(data + DHCP_TRANSACTION_ID_OFFSET); 2486 wma_debug("Pkt_len: %u, Transaction_id: %u", 2487 qdf_cpu_to_be16(pkt_len), qdf_cpu_to_be16(trans_id)); 2488 } 2489 wma_log_pkt_icmpv4(uint8_t * data,uint32_t length)2490 static void wma_log_pkt_icmpv4(uint8_t *data, uint32_t length) 2491 { 2492 uint16_t pkt_len, seq_num; 2493 2494 if (length < WMA_IPV4_PKT_INFO_GET_MIN_LEN) 2495 return; 2496 2497 pkt_len = *(uint16_t *)(data + IPV4_PKT_LEN_OFFSET); 2498 seq_num = *(uint16_t *)(data + ICMP_SEQ_NUM_OFFSET); 2499 wma_debug("Pkt_len: %u, Seq_num: %u", 2500 qdf_cpu_to_be16(pkt_len), qdf_cpu_to_be16(seq_num)); 2501 } 2502 wma_log_pkt_icmpv6(uint8_t * data,uint32_t length)2503 static void wma_log_pkt_icmpv6(uint8_t *data, uint32_t length) 2504 { 2505 uint16_t pkt_len, seq_num; 2506 2507 if (length < WMA_IPV6_PKT_INFO_GET_MIN_LEN) 2508 return; 2509 2510 pkt_len = *(uint16_t *)(data + IPV6_PKT_LEN_OFFSET); 2511 seq_num = *(uint16_t *)(data + ICMPV6_SEQ_NUM_OFFSET); 2512 wma_debug("Pkt_len: %u, Seq_num: %u", 2513 qdf_cpu_to_be16(pkt_len), qdf_cpu_to_be16(seq_num)); 2514 } 2515 wma_log_pkt_ipv4(uint8_t * data,uint32_t length)2516 static void wma_log_pkt_ipv4(uint8_t *data, uint32_t length) 2517 { 2518 uint16_t pkt_len, src_port, dst_port; 2519 char *ip_addr; 2520 2521 if (length < WMA_IPV4_PKT_INFO_GET_MIN_LEN) 2522 return; 2523 2524 pkt_len = *(uint16_t *)(data + IPV4_PKT_LEN_OFFSET); 2525 ip_addr = (char *)(data + IPV4_SRC_ADDR_OFFSET); 2526 wma_nofl_debug("src addr %d:%d:%d:%d", ip_addr[0], ip_addr[1], 2527 ip_addr[2], ip_addr[3]); 2528 ip_addr = (char *)(data + IPV4_DST_ADDR_OFFSET); 2529 wma_nofl_debug("dst addr %d:%d:%d:%d", ip_addr[0], ip_addr[1], 2530 ip_addr[2], ip_addr[3]); 2531 src_port = *(uint16_t *)(data + IPV4_SRC_PORT_OFFSET); 2532 dst_port = *(uint16_t *)(data + IPV4_DST_PORT_OFFSET); 2533 wma_debug("Pkt_len: %u, src_port: %u, dst_port: %u", 2534 qdf_cpu_to_be16(pkt_len), 2535 qdf_cpu_to_be16(src_port), 2536 qdf_cpu_to_be16(dst_port)); 2537 } 2538 wma_log_pkt_ipv6(uint8_t * data,uint32_t length)2539 static void wma_log_pkt_ipv6(uint8_t *data, uint32_t length) 2540 { 2541 uint16_t pkt_len, src_port, dst_port; 2542 char *ip_addr; 2543 2544 if (length < WMA_IPV6_PKT_INFO_GET_MIN_LEN) 2545 return; 2546 2547 pkt_len = *(uint16_t *)(data + IPV6_PKT_LEN_OFFSET); 2548 ip_addr = (char *)(data + IPV6_SRC_ADDR_OFFSET); 2549 wma_nofl_debug("src addr "IPV6_ADDR_STR, ip_addr[0], 2550 ip_addr[1], ip_addr[2], ip_addr[3], ip_addr[4], 2551 ip_addr[5], ip_addr[6], ip_addr[7], ip_addr[8], 2552 ip_addr[9], ip_addr[10], ip_addr[11], 2553 ip_addr[12], ip_addr[13], ip_addr[14], 2554 ip_addr[15]); 2555 ip_addr = (char *)(data + IPV6_DST_ADDR_OFFSET); 2556 wma_nofl_debug("dst addr "IPV6_ADDR_STR, ip_addr[0], 2557 ip_addr[1], ip_addr[2], ip_addr[3], ip_addr[4], 2558 ip_addr[5], ip_addr[6], ip_addr[7], ip_addr[8], 2559 ip_addr[9], ip_addr[10], ip_addr[11], 2560 ip_addr[12], ip_addr[13], ip_addr[14], 2561 ip_addr[15]); 2562 src_port = *(uint16_t *)(data + IPV6_SRC_PORT_OFFSET); 2563 dst_port = *(uint16_t *)(data + IPV6_DST_PORT_OFFSET); 2564 wma_info("Pkt_len: %u, src_port: %u, dst_port: %u", 2565 qdf_cpu_to_be16(pkt_len), 2566 qdf_cpu_to_be16(src_port), 2567 qdf_cpu_to_be16(dst_port)); 2568 } 2569 wma_log_pkt_tcpv4(uint8_t * data,uint32_t length)2570 static void wma_log_pkt_tcpv4(uint8_t *data, uint32_t length) 2571 { 2572 uint32_t seq_num; 2573 2574 if (length < WMA_IPV4_PKT_INFO_GET_MIN_LEN) 2575 return; 2576 2577 seq_num = *(uint32_t *)(data + IPV4_TCP_SEQ_NUM_OFFSET); 2578 wma_debug("TCP_seq_num: %u", qdf_cpu_to_be16(seq_num)); 2579 } 2580 wma_log_pkt_tcpv6(uint8_t * data,uint32_t length)2581 static void wma_log_pkt_tcpv6(uint8_t *data, uint32_t length) 2582 { 2583 uint32_t seq_num; 2584 2585 if (length < WMA_IPV6_PKT_INFO_GET_MIN_LEN) 2586 return; 2587 2588 seq_num = *(uint32_t *)(data + IPV6_TCP_SEQ_NUM_OFFSET); 2589 wma_debug("TCP_seq_num: %u", qdf_cpu_to_be16(seq_num)); 2590 } 2591 wma_wow_inc_wake_lock_stats_by_dst_addr(t_wma_handle * wma,uint8_t vdev_id,uint8_t * dest_mac)2592 static void wma_wow_inc_wake_lock_stats_by_dst_addr(t_wma_handle *wma, 2593 uint8_t vdev_id, 2594 uint8_t *dest_mac) 2595 { 2596 ucfg_mc_cp_stats_inc_wake_lock_stats_by_dst_addr(wma->psoc, 2597 vdev_id, 2598 dest_mac); 2599 } 2600 wma_wow_inc_wake_lock_stats_by_protocol(t_wma_handle * wma,uint8_t vdev_id,enum qdf_proto_subtype proto_subtype)2601 static void wma_wow_inc_wake_lock_stats_by_protocol(t_wma_handle *wma, 2602 uint8_t vdev_id, enum qdf_proto_subtype proto_subtype) 2603 { 2604 ucfg_mc_cp_stats_inc_wake_lock_stats_by_protocol(wma->psoc, 2605 vdev_id, 2606 proto_subtype); 2607 } 2608 2609 /** 2610 * wma_wow_parse_data_pkt() - API to parse data buffer for data 2611 * packet that resulted in WOW wakeup. 2612 * @stats: per-vdev stats for tracking packet types 2613 * @data: Pointer to data buffer 2614 * @length: data buffer length 2615 * 2616 * This function parses the data buffer received (first few bytes of 2617 * skb->data) to get information like src mac addr, dst mac addr, packet 2618 * len, seq_num, etc. It also increments stats for different packet types. 2619 * 2620 * Return: void 2621 */ wma_wow_parse_data_pkt(t_wma_handle * wma,uint8_t vdev_id,uint8_t * data,uint32_t length)2622 static void wma_wow_parse_data_pkt(t_wma_handle *wma, 2623 uint8_t vdev_id, uint8_t *data, 2624 uint32_t length) 2625 { 2626 uint8_t *src_mac; 2627 uint8_t *dest_mac; 2628 const char *proto_subtype_name; 2629 enum qdf_proto_subtype proto_subtype; 2630 2631 wma_debug("packet length: %u", length); 2632 if (length < QDF_NBUF_TRAC_IPV4_OFFSET) 2633 return; 2634 2635 src_mac = data + QDF_NBUF_SRC_MAC_OFFSET; 2636 dest_mac = data + QDF_NBUF_DEST_MAC_OFFSET; 2637 wma_conditional_log(is_wakeup_event_console_logs_enabled, 2638 "Src_mac: " QDF_MAC_ADDR_FMT ", Dst_mac: " 2639 QDF_MAC_ADDR_FMT, QDF_MAC_ADDR_REF(src_mac), 2640 QDF_MAC_ADDR_REF(dest_mac)); 2641 2642 wma_wow_inc_wake_lock_stats_by_dst_addr(wma, vdev_id, dest_mac); 2643 2644 proto_subtype = wma_wow_get_pkt_proto_subtype(data, length); 2645 proto_subtype_name = wma_pkt_proto_subtype_to_string(proto_subtype); 2646 if (proto_subtype_name) 2647 wma_conditional_log(is_wakeup_event_console_logs_enabled, 2648 "WOW Wakeup: %s rcvd", proto_subtype_name); 2649 2650 switch (proto_subtype) { 2651 case QDF_PROTO_EAPOL_M1: 2652 case QDF_PROTO_EAPOL_M2: 2653 case QDF_PROTO_EAPOL_M3: 2654 case QDF_PROTO_EAPOL_M4: 2655 wma_log_pkt_eapol(data, length); 2656 break; 2657 2658 case QDF_PROTO_DHCP_DISCOVER: 2659 case QDF_PROTO_DHCP_REQUEST: 2660 case QDF_PROTO_DHCP_OFFER: 2661 case QDF_PROTO_DHCP_ACK: 2662 case QDF_PROTO_DHCP_NACK: 2663 case QDF_PROTO_DHCP_RELEASE: 2664 case QDF_PROTO_DHCP_INFORM: 2665 case QDF_PROTO_DHCP_DECLINE: 2666 wma_log_pkt_dhcp(data, length); 2667 break; 2668 2669 case QDF_PROTO_ICMP_REQ: 2670 case QDF_PROTO_ICMP_RES: 2671 wma_wow_inc_wake_lock_stats_by_protocol(wma, vdev_id, 2672 proto_subtype); 2673 wma_log_pkt_icmpv4(data, length); 2674 break; 2675 2676 case QDF_PROTO_ICMPV6_REQ: 2677 case QDF_PROTO_ICMPV6_RES: 2678 case QDF_PROTO_ICMPV6_RS: 2679 case QDF_PROTO_ICMPV6_RA: 2680 case QDF_PROTO_ICMPV6_NS: 2681 case QDF_PROTO_ICMPV6_NA: 2682 wma_wow_inc_wake_lock_stats_by_protocol(wma, vdev_id, 2683 proto_subtype); 2684 wma_log_pkt_icmpv6(data, length); 2685 break; 2686 2687 case QDF_PROTO_IPV4_UDP: 2688 wma_log_pkt_ipv4(data, length); 2689 break; 2690 case QDF_PROTO_IPV4_TCP: 2691 wma_log_pkt_ipv4(data, length); 2692 wma_log_pkt_tcpv4(data, length); 2693 break; 2694 2695 case QDF_PROTO_IPV6_UDP: 2696 wma_log_pkt_ipv6(data, length); 2697 break; 2698 case QDF_PROTO_IPV6_TCP: 2699 wma_log_pkt_ipv6(data, length); 2700 wma_log_pkt_tcpv6(data, length); 2701 break; 2702 default: 2703 break; 2704 } 2705 } 2706 2707 /** 2708 * wma_wow_dump_mgmt_buffer() - API to parse data buffer for mgmt. 2709 * packet that resulted in WOW wakeup. 2710 * @wow_packet_buffer: Pointer to data buffer 2711 * @buf_len: length of data buffer 2712 * 2713 * This function parses the data buffer received (802.11 header) 2714 * to get information like src mac addr, dst mac addr, seq_num, 2715 * frag_num, etc. 2716 * 2717 * Return: void 2718 */ wma_wow_dump_mgmt_buffer(uint8_t * wow_packet_buffer,uint32_t buf_len)2719 static void wma_wow_dump_mgmt_buffer(uint8_t *wow_packet_buffer, 2720 uint32_t buf_len) 2721 { 2722 struct ieee80211_frame_addr4 *wh; 2723 2724 wma_debug("wow_buf_pkt_len: %u", buf_len); 2725 wh = (struct ieee80211_frame_addr4 *) 2726 (wow_packet_buffer); 2727 if (buf_len >= sizeof(struct ieee80211_frame)) { 2728 uint8_t to_from_ds, frag_num; 2729 uint32_t seq_num; 2730 2731 wma_conditional_log(is_wakeup_event_console_logs_enabled, 2732 "RA: " QDF_MAC_ADDR_FMT " TA: " 2733 QDF_MAC_ADDR_FMT, 2734 QDF_MAC_ADDR_REF(wh->i_addr1), 2735 QDF_MAC_ADDR_REF(wh->i_addr2)); 2736 2737 wma_conditional_log(is_wakeup_event_console_logs_enabled, 2738 "TO_DS: %u, FROM_DS: %u", 2739 wh->i_fc[1] & IEEE80211_FC1_DIR_TODS, 2740 wh->i_fc[1] & IEEE80211_FC1_DIR_FROMDS); 2741 2742 to_from_ds = wh->i_fc[1] & IEEE80211_FC1_DIR_MASK; 2743 2744 switch (to_from_ds) { 2745 case IEEE80211_FC1_DIR_NODS: 2746 wma_conditional_log( 2747 is_wakeup_event_console_logs_enabled, 2748 "BSSID: " QDF_MAC_ADDR_FMT, 2749 QDF_MAC_ADDR_REF(wh->i_addr3)); 2750 break; 2751 case IEEE80211_FC1_DIR_TODS: 2752 wma_conditional_log( 2753 is_wakeup_event_console_logs_enabled, 2754 "DA: " QDF_MAC_ADDR_FMT, 2755 QDF_MAC_ADDR_REF(wh->i_addr3)); 2756 break; 2757 case IEEE80211_FC1_DIR_FROMDS: 2758 wma_conditional_log( 2759 is_wakeup_event_console_logs_enabled, 2760 "SA: " QDF_MAC_ADDR_FMT, 2761 QDF_MAC_ADDR_REF(wh->i_addr3)); 2762 break; 2763 case IEEE80211_FC1_DIR_DSTODS: 2764 if (buf_len >= sizeof(struct ieee80211_frame_addr4)) 2765 wma_conditional_log( 2766 is_wakeup_event_console_logs_enabled, 2767 "DA: " QDF_MAC_ADDR_FMT " SA: " 2768 QDF_MAC_ADDR_FMT, 2769 QDF_MAC_ADDR_REF(wh->i_addr3), 2770 QDF_MAC_ADDR_REF(wh->i_addr4)); 2771 break; 2772 } 2773 2774 seq_num = (((*(uint16_t *)wh->i_seq) & 2775 IEEE80211_SEQ_SEQ_MASK) >> 2776 IEEE80211_SEQ_SEQ_SHIFT); 2777 frag_num = (((*(uint16_t *)wh->i_seq) & 2778 IEEE80211_SEQ_FRAG_MASK) >> 2779 IEEE80211_SEQ_FRAG_SHIFT); 2780 2781 wma_conditional_log(is_wakeup_event_console_logs_enabled, 2782 "SEQ_NUM: %u, FRAG_NUM: %u", seq_num, 2783 frag_num); 2784 } else { 2785 wma_err("Insufficient buffer length for mgmt. packet"); 2786 } 2787 } 2788 2789 /** 2790 * wma_acquire_wakelock() - conditionally acquires a wakelock base on wake reason 2791 * @wma: the wma handle with the wakelocks to acquire 2792 * @wake_reason: wow wakeup reason 2793 * 2794 * Return: None 2795 */ wma_acquire_wow_wakelock(t_wma_handle * wma,int wake_reason)2796 static void wma_acquire_wow_wakelock(t_wma_handle *wma, int wake_reason) 2797 { 2798 qdf_wake_lock_t *wl; 2799 uint32_t ms; 2800 2801 switch (wake_reason) { 2802 case WOW_REASON_AUTH_REQ_RECV: 2803 wl = &wma->wow_auth_req_wl; 2804 ms = WMA_AUTH_REQ_RECV_WAKE_LOCK_TIMEOUT; 2805 break; 2806 case WOW_REASON_ASSOC_REQ_RECV: 2807 wl = &wma->wow_assoc_req_wl; 2808 ms = WMA_ASSOC_REQ_RECV_WAKE_LOCK_DURATION; 2809 break; 2810 case WOW_REASON_DEAUTH_RECVD: 2811 wl = &wma->wow_deauth_rec_wl; 2812 ms = WMA_DEAUTH_RECV_WAKE_LOCK_DURATION; 2813 break; 2814 case WOW_REASON_DISASSOC_RECVD: 2815 wl = &wma->wow_disassoc_rec_wl; 2816 ms = WMA_DISASSOC_RECV_WAKE_LOCK_DURATION; 2817 break; 2818 case WOW_REASON_AP_ASSOC_LOST: 2819 wl = &wma->wow_ap_assoc_lost_wl; 2820 ms = WMA_BMISS_EVENT_WAKE_LOCK_DURATION; 2821 break; 2822 #ifdef FEATURE_WLAN_AUTO_SHUTDOWN 2823 case WOW_REASON_HOST_AUTO_SHUTDOWN: 2824 wl = &wma->wow_auto_shutdown_wl; 2825 ms = WMA_AUTO_SHUTDOWN_WAKE_LOCK_DURATION; 2826 break; 2827 #endif 2828 case WOW_REASON_ROAM_HO: 2829 wl = &wma->roam_ho_wl; 2830 ms = WMA_ROAM_HO_WAKE_LOCK_DURATION; 2831 break; 2832 case WOW_REASON_ROAM_PREAUTH_START: 2833 wl = &wma->roam_preauth_wl; 2834 ms = WMA_ROAM_PREAUTH_WAKE_LOCK_DURATION; 2835 break; 2836 case WOW_REASON_PROBE_REQ_WPS_IE_RECV: 2837 wl = &wma->probe_req_wps_wl; 2838 ms = WMA_REASON_PROBE_REQ_WPS_IE_RECV_DURATION; 2839 break; 2840 default: 2841 return; 2842 } 2843 2844 wma_alert("Holding %d msec wake_lock", ms); 2845 cds_host_diag_log_work(wl, ms, WIFI_POWER_EVENT_WAKELOCK_WOW); 2846 qdf_wake_lock_timeout_acquire(wl, ms); 2847 } 2848 2849 /** 2850 * wma_wake_reason_ap_assoc_lost() - WOW_REASON_AP_ASSOC_LOST handler 2851 * @wma: Pointer to wma handle 2852 * @event: pointer to piggybacked WMI_ROAM_EVENTID_param_tlvs buffer 2853 * @len: length of the event buffer 2854 * 2855 * Return: Errno 2856 */ 2857 static int wma_wake_reason_ap_assoc_lost(t_wma_handle * wma,void * event,uint32_t len)2858 wma_wake_reason_ap_assoc_lost(t_wma_handle *wma, void *event, uint32_t len) 2859 { 2860 WMI_ROAM_EVENTID_param_tlvs *event_param; 2861 wmi_roam_event_fixed_param *roam_event; 2862 2863 event_param = event; 2864 if (!event_param) { 2865 wma_err("AP Assoc Lost event data is null"); 2866 return -EINVAL; 2867 } 2868 2869 roam_event = event_param->fixed_param; 2870 wma_alert("Beacon miss indication on vdev %d", roam_event->vdev_id); 2871 2872 wma_beacon_miss_handler(wma, roam_event->vdev_id, roam_event->rssi); 2873 2874 return 0; 2875 } 2876 wma_vdev_type_str(uint32_t vdev_type)2877 static const char *wma_vdev_type_str(uint32_t vdev_type) 2878 { 2879 switch (vdev_type) { 2880 case WMI_VDEV_TYPE_AP: 2881 return "AP"; 2882 case WMI_VDEV_TYPE_STA: 2883 return "STA"; 2884 case WMI_VDEV_TYPE_IBSS: 2885 return "IBSS"; 2886 case WMI_VDEV_TYPE_MONITOR: 2887 return "MONITOR"; 2888 case WMI_VDEV_TYPE_NAN: 2889 return "NAN"; 2890 case WMI_VDEV_TYPE_OCB: 2891 return "OCB"; 2892 case WMI_VDEV_TYPE_NDI: 2893 return "NDI"; 2894 default: 2895 return "unknown"; 2896 } 2897 } 2898 wma_wake_event_packet(t_wma_handle * wma,WMI_WOW_WAKEUP_HOST_EVENTID_param_tlvs * event_param,uint32_t length)2899 static int wma_wake_event_packet( 2900 t_wma_handle *wma, 2901 WMI_WOW_WAKEUP_HOST_EVENTID_param_tlvs *event_param, 2902 uint32_t length) 2903 { 2904 WOW_EVENT_INFO_fixed_param *wake_info; 2905 struct wma_txrx_node *vdev; 2906 uint8_t *packet; 2907 uint32_t packet_len; 2908 2909 if (event_param->num_wow_packet_buffer <= 4) { 2910 wma_err("Invalid wow packet buffer from firmware %u", 2911 event_param->num_wow_packet_buffer); 2912 return -EINVAL; 2913 } 2914 /* first 4 bytes are the length, followed by the buffer */ 2915 packet_len = *(uint32_t *)event_param->wow_packet_buffer; 2916 packet = event_param->wow_packet_buffer + 4; 2917 2918 if (!packet_len) { 2919 wma_err("Wake event packet is empty"); 2920 return 0; 2921 } 2922 2923 if (packet_len > (event_param->num_wow_packet_buffer - 4)) { 2924 wma_err("Invalid packet_len from firmware, packet_len: %u, num_wow_packet_buffer: %u", 2925 packet_len, 2926 event_param->num_wow_packet_buffer); 2927 return -EINVAL; 2928 } 2929 2930 wake_info = event_param->fixed_param; 2931 2932 wma_debug("Number of delayed packets received = %d", 2933 wake_info->delayed_pkt_count); 2934 2935 switch (wake_info->wake_reason) { 2936 case WOW_REASON_AUTH_REQ_RECV: 2937 case WOW_REASON_ASSOC_REQ_RECV: 2938 case WOW_REASON_DEAUTH_RECVD: 2939 case WOW_REASON_DISASSOC_RECVD: 2940 case WOW_REASON_ASSOC_RES_RECV: 2941 case WOW_REASON_REASSOC_REQ_RECV: 2942 case WOW_REASON_REASSOC_RES_RECV: 2943 case WOW_REASON_BEACON_RECV: 2944 case WOW_REASON_ACTION_FRAME_RECV: 2945 /* management frame case */ 2946 wma_wow_dump_mgmt_buffer(packet, packet_len); 2947 break; 2948 2949 case WOW_REASON_BPF_ALLOW: 2950 case WOW_REASON_PATTERN_MATCH_FOUND: 2951 case WOW_REASON_RA_MATCH: 2952 case WOW_REASON_RECV_MAGIC_PATTERN: 2953 case WOW_REASON_PACKET_FILTER_MATCH: 2954 case WOW_REASON_DELAYED_WAKEUP_HOST_CFG_TIMER_ELAPSED: 2955 case WOW_REASON_DELAYED_WAKEUP_DATA_STORE_LIST_FULL: 2956 wma_info("Wake event packet:"); 2957 qdf_trace_hex_dump(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_DEBUG, 2958 packet, packet_len); 2959 2960 vdev = &wma->interfaces[wake_info->vdev_id]; 2961 wma_wow_parse_data_pkt(wma, wake_info->vdev_id, 2962 packet, packet_len); 2963 break; 2964 2965 case WOW_REASON_PAGE_FAULT: 2966 /* 2967 * In case PAGE_FAULT occurs on non-DRV platform, 2968 * dump event buffer which contains more info regarding 2969 * current page fault. 2970 */ 2971 wma_info("PF occurs during suspend: packet_len %u", 2972 packet_len); 2973 qdf_trace_hex_dump(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_INFO, 2974 packet, packet_len); 2975 break; 2976 2977 default: 2978 return -EINVAL; 2979 } 2980 2981 return 0; 2982 } 2983 wma_wake_event_no_payload(t_wma_handle * wma,WMI_WOW_WAKEUP_HOST_EVENTID_param_tlvs * event_param,uint32_t length)2984 static int wma_wake_event_no_payload( 2985 t_wma_handle *wma, 2986 WMI_WOW_WAKEUP_HOST_EVENTID_param_tlvs *event_param, 2987 uint32_t length) 2988 { 2989 WOW_EVENT_INFO_fixed_param *wake_info = event_param->fixed_param; 2990 2991 switch (wake_info->wake_reason) { 2992 case WOW_REASON_HOST_AUTO_SHUTDOWN: 2993 return wma_wake_reason_auto_shutdown(); 2994 2995 case WOW_REASON_NLOD: 2996 return wma_wake_reason_nlod(wma, wake_info->vdev_id); 2997 2998 case WOW_REASON_GENERIC_WAKE: 2999 case WOW_REASON_ROAM_STATS: 3000 case WOW_REASON_RTT_11AZ: 3001 wma_info("Wake reason %s", 3002 wma_wow_wake_reason_str(wake_info->wake_reason)); 3003 return 0; 3004 3005 default: 3006 return 0; 3007 } 3008 } 3009 wma_wake_event_piggybacked(t_wma_handle * wma,WMI_WOW_WAKEUP_HOST_EVENTID_param_tlvs * event_param,uint32_t length)3010 static int wma_wake_event_piggybacked( 3011 t_wma_handle *wma, 3012 WMI_WOW_WAKEUP_HOST_EVENTID_param_tlvs *event_param, 3013 uint32_t length) 3014 { 3015 int errno = 0; 3016 void *pb_event; 3017 uint32_t pb_event_len; 3018 uint32_t wake_reason; 3019 uint32_t event_id; 3020 uint8_t *bssid; 3021 tpDeleteStaContext del_sta_ctx; 3022 3023 /* 3024 * There are "normal" cases where a wake reason that usually contains a 3025 * piggybacked event is empty. In these cases we just want to wake up, 3026 * and no action is needed. Bail out now if that is the case. 3027 */ 3028 if (!event_param->wow_packet_buffer || 3029 event_param->num_wow_packet_buffer <= 4) { 3030 wma_err("Invalid wow packet buffer from firmware %u", 3031 event_param->num_wow_packet_buffer); 3032 return 0; 3033 } 3034 3035 bssid = wma_get_vdev_bssid 3036 (wma->interfaces[event_param->fixed_param->vdev_id].vdev); 3037 if (!bssid) { 3038 wma_err("Failed to get bssid for vdev_%d", 3039 event_param->fixed_param->vdev_id); 3040 return 0; 3041 } 3042 wake_reason = event_param->fixed_param->wake_reason; 3043 3044 /* parse piggybacked event from param buffer */ 3045 { 3046 int ret_code; 3047 uint8_t *pb_event_buf; 3048 uint32_t tag; 3049 3050 /* first 4 bytes are the length, followed by the buffer */ 3051 pb_event_len = *(uint32_t *)event_param->wow_packet_buffer; 3052 if (pb_event_len > (event_param->num_wow_packet_buffer - 4)) { 3053 wma_err("Invalid pb_event_len from firmware, pb_event_len: %u, num_wow_packet_buffer: %u", 3054 pb_event_len, 3055 event_param->num_wow_packet_buffer); 3056 return -EINVAL; 3057 } 3058 pb_event_buf = event_param->wow_packet_buffer + 4; 3059 3060 wma_debug("piggybacked event buffer:"); 3061 qdf_trace_hex_dump(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_DEBUG, 3062 pb_event_buf, pb_event_len); 3063 3064 tag = WMITLV_GET_TLVTAG(WMITLV_GET_HDR(pb_event_buf)); 3065 event_id = wow_get_wmi_eventid(wake_reason, tag); 3066 if (!event_id) { 3067 wma_err("Unable to find Event Id"); 3068 return -EINVAL; 3069 } 3070 3071 ret_code = wmitlv_check_and_pad_event_tlvs(wma, pb_event_buf, 3072 pb_event_len, 3073 event_id, &pb_event); 3074 if (ret_code) { 3075 wma_err("Bad TLVs; len:%d, event_id:%d, status:%d", 3076 pb_event_len, event_id, ret_code); 3077 return -EINVAL; 3078 } 3079 } 3080 3081 switch (wake_reason) { 3082 case WOW_REASON_AP_ASSOC_LOST: 3083 errno = wma_wake_reason_ap_assoc_lost(wma, pb_event, 3084 pb_event_len); 3085 break; 3086 3087 #ifdef FEATURE_WLAN_SCAN_PNO 3088 case WOW_REASON_NLO_SCAN_COMPLETE: 3089 errno = target_if_nlo_complete_handler(wma, pb_event, 3090 pb_event_len); 3091 break; 3092 #endif /* FEATURE_WLAN_SCAN_PNO */ 3093 3094 case WOW_REASON_CSA_EVENT: 3095 errno = wma_csa_offload_handler(wma, pb_event, pb_event_len); 3096 break; 3097 3098 /* 3099 * WOW_REASON_LOW_RSSI is used for following roaming events - 3100 * WMI_ROAM_REASON_BETTER_AP, WMI_ROAM_REASON_BMISS, 3101 * WMI_ROAM_REASON_SUITABLE_AP will be handled by 3102 * wma_roam_event_callback(). 3103 * WOW_REASON_ROAM_HO is associated with 3104 * WMI_ROAM_REASON_HO_FAILED event and it will be handled by 3105 * wma_roam_event_callback(). 3106 */ 3107 case WOW_REASON_LOW_RSSI: 3108 case WOW_REASON_ROAM_HO: 3109 wlan_roam_debug_log(event_param->fixed_param->vdev_id, 3110 DEBUG_WOW_ROAM_EVENT, 3111 DEBUG_INVALID_PEER_ID, 3112 NULL, NULL, wake_reason, 3113 pb_event_len); 3114 if (pb_event_len > 0) { 3115 errno = target_if_cm_roam_event(wma, pb_event, 3116 pb_event_len); 3117 } else { 3118 /* 3119 * No wow_packet_buffer means a better AP beacon 3120 * will follow in a later event. 3121 */ 3122 wma_debug("Host woken up because of better AP beacon"); 3123 } 3124 break; 3125 3126 case WOW_REASON_CLIENT_KICKOUT_EVENT: 3127 errno = wma_peer_sta_kickout_event_handler(wma, pb_event, 3128 pb_event_len); 3129 break; 3130 3131 #ifdef FEATURE_WLAN_EXTSCAN 3132 case WOW_REASON_EXTSCAN: 3133 errno = wma_extscan_wow_event_callback(wma, pb_event, 3134 pb_event_len); 3135 break; 3136 #endif 3137 3138 case WOW_REASON_RSSI_BREACH_EVENT: 3139 errno = wma_rssi_breached_event_handler(wma, pb_event, 3140 pb_event_len); 3141 break; 3142 3143 case WOW_REASON_NAN_EVENT: 3144 errno = wma_nan_rsp_handler_callback(wma, pb_event, 3145 pb_event_len); 3146 break; 3147 3148 case WOW_REASON_NAN_DATA: 3149 errno = wma_ndp_wow_event_callback(wma, pb_event, pb_event_len, 3150 event_id); 3151 break; 3152 3153 #ifdef FEATURE_WLAN_TDLS 3154 case WOW_REASON_TDLS_CONN_TRACKER_EVENT: 3155 errno = wma_tdls_event_handler(wma, pb_event, pb_event_len); 3156 break; 3157 #endif 3158 3159 case WOW_REASON_TIMER_INTR_RECV: 3160 /* 3161 * Right now firmware is not returning any cookie host has 3162 * programmed. So do not check for cookie. 3163 */ 3164 wma_err("WOW_REASON_TIMER_INTR_RECV received, indicating key exchange did not finish. Initiate disconnect"); 3165 del_sta_ctx = qdf_mem_malloc(sizeof(*del_sta_ctx)); 3166 if (!del_sta_ctx) 3167 break; 3168 3169 del_sta_ctx->is_tdls = false; 3170 del_sta_ctx->vdev_id = event_param->fixed_param->vdev_id; 3171 qdf_mem_copy(del_sta_ctx->addr2, bssid, QDF_MAC_ADDR_SIZE); 3172 qdf_mem_copy(del_sta_ctx->bssId, bssid, QDF_MAC_ADDR_SIZE); 3173 del_sta_ctx->reasonCode = HAL_DEL_STA_REASON_CODE_KEEP_ALIVE; 3174 wma_send_msg(wma, SIR_LIM_DELETE_STA_CONTEXT_IND, del_sta_ctx, 3175 0); 3176 break; 3177 case WOW_REASON_ROAM_PMKID_REQUEST: 3178 wma_debug("Host woken up because of PMKID request event"); 3179 errno = target_if_pmkid_request_event_handler(wma, 3180 pb_event, pb_event_len); 3181 break; 3182 case WOW_REASON_VDEV_DISCONNECT: 3183 wma_debug("Host woken up because of vdev disconnect event"); 3184 errno = target_if_cm_roam_vdev_disconnect_event_handler(wma, 3185 pb_event, pb_event_len); 3186 break; 3187 default: 3188 wma_err("Wake reason %s(%u) is not a piggybacked event", 3189 wma_wow_wake_reason_str(wake_reason), wake_reason); 3190 errno = -EINVAL; 3191 break; 3192 } 3193 3194 wmitlv_free_allocated_event_tlvs(event_id, &pb_event); 3195 3196 return errno; 3197 } 3198 wma_debug_assert_page_fault_wakeup(uint32_t reason)3199 static void wma_debug_assert_page_fault_wakeup(uint32_t reason) 3200 { 3201 /* During DRV if page fault wake up then assert */ 3202 if ((WOW_REASON_PAGE_FAULT == reason) && (qdf_is_drv_connected())) 3203 QDF_DEBUG_PANIC("Unexpected page fault wake up detected during DRV wow"); 3204 } 3205 wma_wake_event_log_reason(t_wma_handle * wma,WOW_EVENT_INFO_fixed_param * wake_info)3206 static void wma_wake_event_log_reason(t_wma_handle *wma, 3207 WOW_EVENT_INFO_fixed_param *wake_info) 3208 { 3209 struct wma_txrx_node *vdev; 3210 3211 /* "Unspecified" means APPS triggered wake, else firmware triggered */ 3212 if (wake_info->wake_reason != WOW_REASON_UNSPECIFIED) { 3213 vdev = &wma->interfaces[wake_info->vdev_id]; 3214 wma_nofl_info("WLAN triggered wakeup: %s (%d), vdev: %d (%s)", 3215 wma_wow_wake_reason_str(wake_info->wake_reason), 3216 wake_info->wake_reason, 3217 wake_info->vdev_id, 3218 wma_vdev_type_str(vdev->type)); 3219 wma_debug_assert_page_fault_wakeup(wake_info->wake_reason); 3220 } else if (!wmi_get_runtime_pm_inprogress(wma->wmi_handle)) { 3221 wma_nofl_info("Non-WLAN triggered wakeup: %s (%d)", 3222 wma_wow_wake_reason_str(wake_info->wake_reason), 3223 wake_info->wake_reason); 3224 } 3225 3226 qdf_wow_wakeup_host_event(wake_info->wake_reason); 3227 qdf_wma_wow_wakeup_stats_event(wma); 3228 } 3229 wma_wow_pagefault_action_cb(void * buf)3230 static QDF_STATUS wma_wow_pagefault_action_cb(void *buf) 3231 { 3232 struct mac_context *mac = cds_get_context(QDF_MODULE_ID_PE); 3233 3234 if (!mac) { 3235 wma_err("NULL mac ptr"); 3236 return QDF_STATUS_E_INVAL; 3237 } 3238 3239 return mac->sme.pagefault_action_cb(buf, WLAN_WMA_PF_APPS_NOTIFY_BUF_LEN); 3240 } 3241 3242 static QDF_STATUS wma_wow_pagefault_add_sym_to_event(tp_wma_handle wma,struct wow_pf_sym * pf_sym)3243 wma_wow_pagefault_add_sym_to_event(tp_wma_handle wma, struct wow_pf_sym *pf_sym) 3244 { 3245 uint8_t *buf_ptr = wma->wma_pf_hist.pf_notify_buf_ptr; 3246 uint32_t buf_len = wma->wma_pf_hist.pf_notify_buf_len; 3247 3248 if (WLAN_WMA_PF_APPS_NOTIFY_BUF_LEN - buf_len < 3249 WLAN_WMA_PER_PF_SYM_NOTIFY_BUF_LEN) { 3250 wma_wow_pagefault_action_cb(buf_ptr); 3251 buf_len = 0; 3252 } 3253 3254 /* Mem zero to send buffer with zero padding */ 3255 if (!buf_len) 3256 qdf_mem_zero(buf_ptr, WLAN_WMA_PF_APPS_NOTIFY_BUF_LEN); 3257 3258 qdf_mem_copy(buf_ptr + buf_len, pf_sym, 3259 WLAN_WMA_PER_PF_SYM_NOTIFY_BUF_LEN); 3260 buf_len += WLAN_WMA_PER_PF_SYM_NOTIFY_BUF_LEN; 3261 3262 wma->wma_pf_hist.pf_notify_buf_len = buf_len; 3263 3264 return QDF_STATUS_SUCCESS; 3265 } 3266 3267 static void wma_wow_pagefault_add_new_sym_from_event(tp_wma_handle wma,struct wow_pf_wakeup_ev_data * pf_sym_list,qdf_time_t cur_time)3268 wma_wow_pagefault_add_new_sym_from_event(tp_wma_handle wma, 3269 struct wow_pf_wakeup_ev_data *pf_sym_list, 3270 qdf_time_t cur_time) 3271 { 3272 uint8_t tbl_idx, ev_lst_idx, new_pf_idx, idx2; 3273 uint8_t new_idx_cnt, cur_idx_cnt, ev_sym_cnt, pf_th; 3274 uint8_t max_sym_count = WLAN_WMA_MAX_PF_SYM; 3275 qdf_time_t new_idx_last_ts, cur_idx_last_ts; 3276 qdf_time_t new_idx_old_ts, cur_idx_old_ts; 3277 struct wma_pf_sym *cur_pf_entry, *new_pf_entry; 3278 struct wma_pf_sym_hist *pf_sym_hist = &wma->wma_pf_hist; 3279 3280 pf_th = wlan_pmo_get_min_pagefault_wakeups_for_action(wma->psoc); 3281 for (tbl_idx = 0; tbl_idx < max_sym_count; tbl_idx++) { 3282 if (!pf_sym_list->pending_pf_syms) 3283 break; 3284 3285 new_pf_idx = tbl_idx; 3286 new_pf_entry = &pf_sym_hist->wma_pf_sym[tbl_idx]; 3287 new_idx_cnt = new_pf_entry->pf_sym.count; 3288 new_idx_last_ts = new_pf_entry->pf_ev_ts[new_idx_cnt - 1]; 3289 new_idx_old_ts = new_pf_entry->pf_ev_ts[0]; 3290 3291 for (ev_lst_idx = 0; ev_lst_idx < pf_sym_list->num_pf_syms; 3292 ev_lst_idx++) { 3293 if (!pf_sym_list->pf_sym[ev_lst_idx].count) 3294 continue; 3295 3296 /* Add the sym that already met threshold to the buf */ 3297 if (pf_sym_list->pf_sym[ev_lst_idx].count >= pf_th) { 3298 wma_wow_pagefault_add_sym_to_event(wma, 3299 pf_sym_list->pf_sym); 3300 pf_sym_list->pf_sym[ev_lst_idx].count = 0x0; 3301 pf_sym_list->pending_pf_syms--; 3302 continue; 3303 } 3304 3305 ev_sym_cnt = pf_sym_list->pf_sym[ev_lst_idx].count; 3306 3307 /* If current entry is NULL, add the symbol here */ 3308 if (!new_idx_cnt) 3309 goto add_sym; 3310 3311 /* Replace event if count is equal as current event 3312 * is latest and don't replace symbol from current event 3313 */ 3314 if (new_idx_cnt > ev_sym_cnt || 3315 qdf_system_time_after_eq(new_idx_last_ts, cur_time)) 3316 break; 3317 3318 for (idx2 = tbl_idx + 1; idx2 < max_sym_count; idx2++) { 3319 cur_pf_entry = &pf_sym_hist->wma_pf_sym[idx2]; 3320 cur_idx_cnt = cur_pf_entry->pf_sym.count; 3321 cur_idx_last_ts = 3322 cur_pf_entry->pf_ev_ts[cur_idx_cnt - 1]; 3323 cur_idx_old_ts = cur_pf_entry->pf_ev_ts[0]; 3324 3325 if (cur_idx_cnt > new_idx_cnt) 3326 continue; 3327 3328 /* Don't replace symbol from current event */ 3329 if (qdf_system_time_after_eq(cur_idx_last_ts, 3330 cur_time)) { 3331 continue; 3332 } 3333 3334 if (cur_idx_cnt == new_idx_cnt && 3335 qdf_system_time_after_eq(cur_idx_old_ts, 3336 new_idx_old_ts)) { 3337 continue; 3338 } 3339 3340 new_pf_idx = idx2; 3341 new_idx_cnt = cur_idx_cnt; 3342 new_idx_last_ts = cur_idx_last_ts; 3343 new_idx_old_ts = cur_idx_old_ts; 3344 } 3345 3346 add_sym: 3347 /* Replace symbol with current event symbol */ 3348 new_pf_entry = &pf_sym_hist->wma_pf_sym[new_pf_idx]; 3349 new_pf_entry->pf_sym.symbol = 3350 pf_sym_list->pf_sym[ev_lst_idx].symbol; 3351 new_pf_entry->pf_sym.count = ev_sym_cnt; 3352 for (idx2 = 0; idx2 < ev_sym_cnt; idx2++) 3353 new_pf_entry->pf_ev_ts[idx2] = cur_time; 3354 3355 pf_sym_list->pending_pf_syms--; 3356 pf_sym_list->pf_sym[ev_lst_idx].count = 0; 3357 break; 3358 } 3359 } 3360 } 3361 3362 static void wma_wow_pagefault_process_existing_syms(tp_wma_handle wma,struct wma_pf_sym * pf_sym_entry,struct wow_pf_wakeup_ev_data * ev_list,qdf_time_t cur_time)3363 wma_wow_pagefault_process_existing_syms(tp_wma_handle wma, 3364 struct wma_pf_sym *pf_sym_entry, 3365 struct wow_pf_wakeup_ev_data *ev_list, 3366 qdf_time_t cur_time) 3367 { 3368 uint8_t ev_idx, add_idx; 3369 uint8_t pf_th, *tbl_sym_cnt, ev_sym_cnt; 3370 3371 pf_th = wlan_pmo_get_min_pagefault_wakeups_for_action(wma->psoc); 3372 tbl_sym_cnt = &pf_sym_entry->pf_sym.count; 3373 3374 for (ev_idx = 0; ev_idx < ev_list->num_pf_syms; ev_idx++) { 3375 /* Ignore if all symbols are processed */ 3376 if (!ev_list->pending_pf_syms) 3377 break; 3378 3379 if (!ev_list->pf_sym[ev_idx].count) 3380 continue; 3381 3382 /* Only process symbol equals current entry in the history */ 3383 if (ev_list->pf_sym[ev_idx].symbol != 3384 pf_sym_entry->pf_sym.symbol) { 3385 continue; 3386 } 3387 3388 ev_sym_cnt = ev_list->pf_sym[ev_idx].count; 3389 3390 /* If symbol reaches threshold, then clear the ts data */ 3391 if (*tbl_sym_cnt + ev_sym_cnt >= pf_th) { 3392 qdf_mem_zero(&pf_sym_entry->pf_ev_ts[0], 3393 (*tbl_sym_cnt * sizeof(qdf_time_t))); 3394 *tbl_sym_cnt += ev_sym_cnt; 3395 wma_wow_pagefault_add_sym_to_event(wma, 3396 &pf_sym_entry->pf_sym); 3397 *tbl_sym_cnt = 0x0; 3398 3399 goto sym_handled; 3400 } 3401 3402 for (add_idx = 0; add_idx < ev_sym_cnt; add_idx++) 3403 pf_sym_entry->pf_ev_ts[(*tbl_sym_cnt)++] = cur_time; 3404 3405 sym_handled: 3406 ev_list->pending_pf_syms--; 3407 ev_list->pf_sym[ev_idx].count = 0; 3408 break; 3409 } 3410 } 3411 3412 static void wma_wow_pagefault_flush_ageout_entries(struct wma_pf_sym * pf_sym_entry,qdf_time_t cutoff_time)3413 wma_wow_pagefault_flush_ageout_entries(struct wma_pf_sym *pf_sym_entry, 3414 qdf_time_t cutoff_time) 3415 { 3416 qdf_time_t entry_ts; 3417 uint8_t *cur_pf_count, pf_ts_idx; 3418 3419 cur_pf_count = &pf_sym_entry->pf_sym.count; 3420 /* Find the count of entries which elapsed cutoff time */ 3421 for (pf_ts_idx = 0; pf_ts_idx < *cur_pf_count; pf_ts_idx++) { 3422 entry_ts = pf_sym_entry->pf_ev_ts[pf_ts_idx]; 3423 if (qdf_system_time_before(cutoff_time, entry_ts)) 3424 break; 3425 } 3426 3427 /* Remove the entries which elapsed cutoff time */ 3428 if (pf_ts_idx > 0) { 3429 *cur_pf_count -= pf_ts_idx; 3430 qdf_mem_copy(&pf_sym_entry->pf_ev_ts[0], 3431 &pf_sym_entry->pf_ev_ts[pf_ts_idx], 3432 (*cur_pf_count * sizeof(qdf_time_t))); 3433 qdf_mem_zero(&pf_sym_entry->pf_ev_ts[*cur_pf_count], 3434 pf_ts_idx * sizeof(qdf_time_t)); 3435 } 3436 } 3437 3438 static QDF_STATUS wma_wow_pagefault_parse_event(struct wlan_objmgr_psoc * psoc,void * ev,uint32_t ev_len,struct wow_pf_wakeup_ev_data * pf_sym_list)3439 wma_wow_pagefault_parse_event(struct wlan_objmgr_psoc *psoc, 3440 void *ev, uint32_t ev_len, 3441 struct wow_pf_wakeup_ev_data *pf_sym_list) 3442 { 3443 WMI_WOW_WAKEUP_HOST_EVENTID_param_tlvs *event_param = ev; 3444 uint8_t *cur_list_count, *pf_sym_addr, buf_idx, sym_idx, i; 3445 uint32_t packet_len, symbol, pf_sym_count; 3446 struct wow_pf_sym tmp_pf_sym; 3447 3448 if (event_param->num_wow_packet_buffer <= sizeof(packet_len)) { 3449 wma_err("Invalid wow packet buffer from FW %u", 3450 event_param->num_wow_packet_buffer); 3451 return QDF_STATUS_E_INVAL; 3452 } 3453 3454 packet_len = *(uint32_t *)event_param->wow_packet_buffer; 3455 if (!packet_len) { 3456 wma_err("Wake event packet is empty"); 3457 return QDF_STATUS_E_INVAL; 3458 } 3459 3460 if (packet_len > 3461 (event_param->num_wow_packet_buffer - sizeof(packet_len))) { 3462 wma_err("Invalid packet_len from firmware, packet_len: %u, num_wow_packet_buffer: %u", 3463 packet_len, event_param->num_wow_packet_buffer); 3464 return QDF_STATUS_E_INVAL; 3465 } 3466 3467 pf_sym_count = packet_len / sizeof(symbol); 3468 /* First 4 bytes following packet len contains UUID */ 3469 pf_sym_count--; 3470 3471 pf_sym_list->pf_sym = 3472 qdf_mem_malloc(pf_sym_count * sizeof(*pf_sym_list->pf_sym)); 3473 if (!pf_sym_list->pf_sym) 3474 return QDF_STATUS_E_NOMEM; 3475 3476 /* First 4 bytes of buffer gives length and next 4 bytes for UUID */ 3477 pf_sym_addr = event_param->wow_packet_buffer + (sizeof(packet_len) * 2); 3478 3479 cur_list_count = &pf_sym_list->num_pf_syms; 3480 for (buf_idx = 0; buf_idx < pf_sym_count; buf_idx++) { 3481 symbol = *(uint32_t *)pf_sym_addr; 3482 3483 /* Ignore invalid symbols */ 3484 if (!symbol || symbol == (uint32_t)-1) 3485 goto iter_next_sym; 3486 3487 for (sym_idx = 0; sym_idx < *cur_list_count; sym_idx++) { 3488 if (pf_sym_list->pf_sym[sym_idx].symbol == symbol) { 3489 pf_sym_list->pf_sym[sym_idx].count++; 3490 goto iter_next_sym; 3491 } 3492 } 3493 3494 pf_sym_list->pf_sym[*cur_list_count].symbol = symbol; 3495 pf_sym_list->pf_sym[*cur_list_count].count++; 3496 (*cur_list_count)++; 3497 3498 iter_next_sym: 3499 pf_sym_addr += sizeof(symbol); 3500 } 3501 3502 pf_sym_list->pending_pf_syms = *cur_list_count; 3503 3504 /* Reorder to prioritize syms with high frequency */ 3505 for (sym_idx = 0; sym_idx < *cur_list_count; sym_idx++) { 3506 for (i = sym_idx + 1; i < *cur_list_count; i++) { 3507 if (pf_sym_list->pf_sym[i].count <= 3508 pf_sym_list->pf_sym[sym_idx].count) { 3509 continue; 3510 } 3511 3512 tmp_pf_sym.symbol = pf_sym_list->pf_sym[sym_idx].symbol; 3513 tmp_pf_sym.count = pf_sym_list->pf_sym[sym_idx].count; 3514 3515 pf_sym_list->pf_sym[sym_idx].symbol = 3516 pf_sym_list->pf_sym[i].symbol; 3517 pf_sym_list->pf_sym[sym_idx].count = 3518 pf_sym_list->pf_sym[i].count; 3519 3520 pf_sym_list->pf_sym[i].symbol = tmp_pf_sym.symbol; 3521 pf_sym_list->pf_sym[i].count = tmp_pf_sym.count; 3522 } 3523 } 3524 3525 return QDF_STATUS_SUCCESS; 3526 } 3527 wma_wow_pagefault_handle_ssr_action(tp_wma_handle wma)3528 static void wma_wow_pagefault_handle_ssr_action(tp_wma_handle wma) 3529 { 3530 QDF_STATUS status; 3531 uint8_t *cur_count, pf_thresh; 3532 qdf_time_t cur_time, cutoff_time; 3533 uint32_t pf_wakeup_intv; 3534 struct wma_pf_sym *pf_sym_entry; 3535 3536 cur_time = qdf_get_system_uptime(); 3537 pf_wakeup_intv = 3538 wlan_pmo_get_interval_for_pagefault_wakeup_counts(wma->psoc); 3539 pf_thresh = wlan_pmo_get_min_pagefault_wakeups_for_action(wma->psoc); 3540 cutoff_time = cur_time - qdf_system_msecs_to_ticks(pf_wakeup_intv); 3541 3542 pf_sym_entry = &wma->wma_pf_hist.wma_pf_sym[0]; 3543 cur_count = &pf_sym_entry->pf_sym.count; 3544 if (cutoff_time < cur_time) { 3545 wma_wow_pagefault_flush_ageout_entries(pf_sym_entry, 3546 cutoff_time); 3547 } 3548 3549 pf_sym_entry->pf_ev_ts[(*cur_count)++] = cur_time; 3550 if (*cur_count < pf_thresh) 3551 return; 3552 3553 /* If SSR threshold condition fails, SSR will not be triggered, so 3554 * save current event and flush oldest entry. 3555 */ 3556 status = wma_wow_pagefault_action_cb(NULL); 3557 if (QDF_IS_STATUS_ERROR(status)) { 3558 (*cur_count)--; 3559 qdf_mem_copy(&pf_sym_entry->pf_ev_ts[0], 3560 &pf_sym_entry->pf_ev_ts[1], 3561 (*cur_count * sizeof(qdf_time_t))); 3562 qdf_mem_zero(&pf_sym_entry->pf_ev_ts[*cur_count], 3563 sizeof(qdf_time_t)); 3564 } 3565 } 3566 3567 static void wma_wow_wakeup_pagefault_notify(tp_wma_handle wma,void * ev,uint32_t ev_len)3568 wma_wow_wakeup_pagefault_notify(tp_wma_handle wma, void *ev, uint32_t ev_len) 3569 { 3570 QDF_STATUS status; 3571 uint32_t pf_wakeup_intv; 3572 qdf_time_t cur_time, cutoff_time; 3573 struct wma_pf_sym *pf_sym_entry; 3574 struct wma_pf_sym_hist *pf_sym_hist = &wma->wma_pf_hist; 3575 struct wlan_objmgr_psoc *psoc = wma->psoc; 3576 uint8_t pf_tbl_idx; 3577 struct wow_pf_wakeup_ev_data pf_sym_list = {0}; 3578 struct mac_context *mac = cds_get_context(QDF_MODULE_ID_PE); 3579 3580 if (!mac) { 3581 wma_debug("MAC context NULL"); 3582 return; 3583 } 3584 3585 if (wlan_pmo_no_op_on_page_fault(psoc)) 3586 return; 3587 3588 if (wmi_get_runtime_pm_inprogress(wma->wmi_handle)) { 3589 wma_debug("Ignore run time pm wakeup"); 3590 return; 3591 } 3592 3593 if (!mac->sme.pagefault_action_cb) { 3594 wma_debug("NULL pagefault action cb"); 3595 return; 3596 } 3597 3598 if (wlan_pmo_enable_ssr_on_page_fault(psoc)) { 3599 wma_wow_pagefault_handle_ssr_action(wma); 3600 return; 3601 } 3602 3603 cur_time = qdf_get_system_uptime(); 3604 pf_wakeup_intv = 3605 wlan_pmo_get_interval_for_pagefault_wakeup_counts(psoc); 3606 cutoff_time = cur_time - qdf_system_msecs_to_ticks(pf_wakeup_intv); 3607 3608 status = wma_wow_pagefault_parse_event(psoc, ev, ev_len, &pf_sym_list); 3609 if (QDF_IS_STATUS_ERROR(status)) { 3610 wma_debug("Failed during page fault payload parse"); 3611 return; 3612 } 3613 3614 qdf_spinlock_acquire(&pf_sym_hist->lock); 3615 for (pf_tbl_idx = 0; pf_tbl_idx < WLAN_WMA_MAX_PF_SYM; pf_tbl_idx++) { 3616 pf_sym_entry = &pf_sym_hist->wma_pf_sym[pf_tbl_idx]; 3617 if (cutoff_time < cur_time) { 3618 wma_wow_pagefault_flush_ageout_entries(pf_sym_entry, 3619 cutoff_time); 3620 } 3621 3622 wma_wow_pagefault_process_existing_syms(wma, pf_sym_entry, 3623 &pf_sym_list, cur_time); 3624 3625 if (!pf_sym_list.pending_pf_syms) 3626 goto send_event; 3627 } 3628 3629 /* Process if any new symbols are present in the event */ 3630 wma_wow_pagefault_add_new_sym_from_event(wma, &pf_sym_list, cur_time); 3631 3632 send_event: 3633 if (pf_sym_hist->pf_notify_buf_len) { 3634 wma_wow_pagefault_action_cb(pf_sym_hist->pf_notify_buf_ptr); 3635 pf_sym_hist->pf_notify_buf_len = 0; 3636 } 3637 3638 qdf_spinlock_release(&pf_sym_hist->lock); 3639 3640 qdf_mem_free(pf_sym_list.pf_sym); 3641 pf_sym_list.pf_sym = NULL; 3642 } 3643 3644 /** 3645 * wma_wow_wakeup_host_event() - wakeup host event handler 3646 * @handle: wma handle 3647 * @event: event data 3648 * @len: buffer length 3649 * 3650 * Handler to catch wow wakeup host event. This event will have 3651 * reason why the firmware has woken the host. 3652 * 3653 * Return: Errno 3654 */ wma_wow_wakeup_host_event(void * handle,uint8_t * event,uint32_t len)3655 int wma_wow_wakeup_host_event(void *handle, uint8_t *event, uint32_t len) 3656 { 3657 int errno; 3658 t_wma_handle *wma = handle; 3659 WMI_WOW_WAKEUP_HOST_EVENTID_param_tlvs *event_param; 3660 WOW_EVENT_INFO_fixed_param *wake_info; 3661 3662 event_param = (WMI_WOW_WAKEUP_HOST_EVENTID_param_tlvs *)event; 3663 if (!event_param) { 3664 wma_err("Wake event data is null"); 3665 return -EINVAL; 3666 } 3667 3668 wake_info = event_param->fixed_param; 3669 3670 if (wake_info->vdev_id >= wma->max_bssid) { 3671 wma_err("received invalid vdev_id %d", wake_info->vdev_id); 3672 return -EINVAL; 3673 } 3674 3675 wma_wake_event_log_reason(wma, wake_info); 3676 if (wake_info->wake_reason == WOW_REASON_PAGE_FAULT) 3677 wma_wow_wakeup_pagefault_notify(wma, event, len); 3678 3679 if (wake_info->wake_reason == WOW_REASON_LOCAL_DATA_UC_DROP) 3680 hif_rtpm_set_autosuspend_delay(WOW_LARGE_RX_RTPM_DELAY); 3681 3682 ucfg_pmo_psoc_wakeup_host_event_received(wma->psoc); 3683 3684 wma_print_wow_stats(wma, wake_info); 3685 /* split based on payload type */ 3686 if (is_piggybacked_event(wake_info->wake_reason)) 3687 errno = wma_wake_event_piggybacked(wma, event_param, len); 3688 else if (event_param->wow_packet_buffer) 3689 errno = wma_wake_event_packet(wma, event_param, len); 3690 else 3691 errno = wma_wake_event_no_payload(wma, event_param, len); 3692 3693 wma_inc_wow_stats(wma, wake_info); 3694 wma_print_wow_stats(wma, wake_info); 3695 wma_acquire_wow_wakelock(wma, wake_info->wake_reason); 3696 3697 return errno; 3698 } 3699 3700 #ifdef FEATURE_WLAN_D0WOW 3701 /** 3702 * wma_d0_wow_disable_ack_event() - wakeup host event handler 3703 * @handle: wma handle 3704 * @event: event data 3705 * @len: buffer length 3706 * 3707 * Handler to catch D0-WOW disable ACK event. This event will have 3708 * reason why the firmware has woken the host. 3709 * This is for backward compatible with cld2.0. 3710 * 3711 * Return: 0 for success or error 3712 */ wma_d0_wow_disable_ack_event(void * handle,uint8_t * event,uint32_t len)3713 int wma_d0_wow_disable_ack_event(void *handle, uint8_t *event, uint32_t len) 3714 { 3715 tp_wma_handle wma = (tp_wma_handle)handle; 3716 WMI_D0_WOW_DISABLE_ACK_EVENTID_param_tlvs *param_buf; 3717 wmi_d0_wow_disable_ack_event_fixed_param *resp_data; 3718 3719 param_buf = (WMI_D0_WOW_DISABLE_ACK_EVENTID_param_tlvs *)event; 3720 if (!param_buf) { 3721 wma_err("Invalid D0-WOW disable ACK event buffer!"); 3722 return -EINVAL; 3723 } 3724 3725 resp_data = param_buf->fixed_param; 3726 3727 ucfg_pmo_psoc_wakeup_host_event_received(wma->psoc); 3728 3729 wma_debug("Received D0-WOW disable ACK"); 3730 3731 return 0; 3732 } 3733 #else wma_d0_wow_disable_ack_event(void * handle,uint8_t * event,uint32_t len)3734 int wma_d0_wow_disable_ack_event(void *handle, uint8_t *event, uint32_t len) 3735 { 3736 return 0; 3737 } 3738 #endif 3739 3740 /** 3741 * wma_pdev_resume_event_handler() - PDEV resume event handler 3742 * @handle: wma handle 3743 * @event: event data 3744 * @len: buffer length 3745 * 3746 * Return: 0 for success or error 3747 */ wma_pdev_resume_event_handler(void * handle,uint8_t * event,uint32_t len)3748 int wma_pdev_resume_event_handler(void *handle, uint8_t *event, uint32_t len) 3749 { 3750 tp_wma_handle wma = (tp_wma_handle) handle; 3751 3752 wma_nofl_info("Received PDEV resume event"); 3753 3754 ucfg_pmo_psoc_wakeup_host_event_received(wma->psoc); 3755 3756 return 0; 3757 } 3758 3759 /** 3760 * wma_del_ts_req() - send DELTS request to fw 3761 * @wma: wma handle 3762 * @msg: delts params 3763 * 3764 * Return: none 3765 */ wma_del_ts_req(tp_wma_handle wma,struct del_ts_params * msg)3766 void wma_del_ts_req(tp_wma_handle wma, struct del_ts_params *msg) 3767 { 3768 if (!wma_is_vdev_valid(msg->sessionId)) { 3769 wma_err("vdev id:%d is not active ", msg->sessionId); 3770 qdf_mem_free(msg); 3771 return; 3772 } 3773 if (wmi_unified_del_ts_cmd(wma->wmi_handle, 3774 msg->sessionId, 3775 TID_TO_WME_AC(msg->userPrio))) { 3776 wma_alert("Failed to send vdev DELTS command"); 3777 } 3778 3779 #ifdef WLAN_FEATURE_ROAM_OFFLOAD 3780 if (msg->setRICparams == true) 3781 wma_set_ric_req(wma, msg, false); 3782 #endif /* WLAN_FEATURE_ROAM_OFFLOAD */ 3783 qdf_mem_free(msg); 3784 } 3785 wma_aggr_qos_req(tp_wma_handle wma,struct aggr_add_ts_param * aggr_qos_rsp_msg)3786 void wma_aggr_qos_req(tp_wma_handle wma, 3787 struct aggr_add_ts_param *aggr_qos_rsp_msg) 3788 { 3789 if (!wma_is_vdev_valid(aggr_qos_rsp_msg->vdev_id)) { 3790 wma_err("vdev id:%d is not active ", 3791 aggr_qos_rsp_msg->vdev_id); 3792 return; 3793 } 3794 wmi_unified_aggr_qos_cmd(wma->wmi_handle, aggr_qos_rsp_msg); 3795 /* send response to upper layers from here only. */ 3796 wma_send_msg_high_priority(wma, WMA_AGGR_QOS_RSP, aggr_qos_rsp_msg, 0); 3797 } 3798 3799 #ifdef FEATURE_WLAN_ESE 3800 /** 3801 * wma_set_tsm_interval() - Set TSM interval 3802 * @req: pointer to ADDTS request 3803 * 3804 * Return: QDF_STATUS_E_FAILURE or QDF_STATUS_SUCCESS 3805 */ wma_set_tsm_interval(struct add_ts_param * req)3806 static QDF_STATUS wma_set_tsm_interval(struct add_ts_param *req) 3807 { 3808 /* 3809 * msmt_interval is in unit called TU (1 TU = 1024 us) 3810 * max value of msmt_interval cannot make resulting 3811 * interval_milliseconds overflow 32 bit 3812 * 3813 */ 3814 uint32_t interval_milliseconds; 3815 3816 interval_milliseconds = (req->tsm_interval * 1024) / 1000; 3817 3818 cdp_tx_set_compute_interval(cds_get_context(QDF_MODULE_ID_SOC), 3819 WMI_PDEV_ID_SOC, 3820 interval_milliseconds); 3821 return QDF_STATUS_SUCCESS; 3822 } 3823 #else wma_set_tsm_interval(struct add_ts_param * req)3824 static inline QDF_STATUS wma_set_tsm_interval(struct add_ts_param *req) 3825 { 3826 return QDF_STATUS_SUCCESS; 3827 } 3828 #endif /* FEATURE_WLAN_ESE */ 3829 3830 /** 3831 * wma_add_ts_req() - send ADDTS request to fw 3832 * @wma: wma handle 3833 * @msg: ADDTS params 3834 * 3835 * Return: none 3836 */ wma_add_ts_req(tp_wma_handle wma,struct add_ts_param * msg)3837 void wma_add_ts_req(tp_wma_handle wma, struct add_ts_param *msg) 3838 { 3839 struct add_ts_param cmd = {0}; 3840 3841 msg->status = QDF_STATUS_SUCCESS; 3842 if (wma_set_tsm_interval(msg) == QDF_STATUS_SUCCESS) { 3843 3844 cmd.vdev_id = msg->vdev_id; 3845 cmd.tspec.tsinfo.traffic.userPrio = 3846 TID_TO_WME_AC(msg->tspec.tsinfo.traffic.userPrio); 3847 cmd.tspec.mediumTime = msg->tspec.mediumTime; 3848 if (wmi_unified_add_ts_cmd(wma->wmi_handle, &cmd)) 3849 msg->status = QDF_STATUS_E_FAILURE; 3850 3851 #ifdef WLAN_FEATURE_ROAM_OFFLOAD 3852 if (msg->set_ric_params) 3853 wma_set_ric_req(wma, msg, true); 3854 #endif /* WLAN_FEATURE_ROAM_OFFLOAD */ 3855 3856 } 3857 wma_send_msg_high_priority(wma, WMA_ADD_TS_RSP, msg, 0); 3858 } 3859 3860 #ifdef FEATURE_WLAN_ESE 3861 3862 #define TSM_DELAY_HISTROGRAM_BINS 4 3863 /** 3864 * wma_process_tsm_stats_req() - process tsm stats request 3865 * @wma_handler - handle to wma 3866 * @pTsmStatsMsg - TSM stats struct that needs to be populated and 3867 * passed in message. 3868 * 3869 * A parallel function to WMA_ProcessTsmStatsReq for pronto. This 3870 * function fetches stats from data path APIs and post 3871 * WMA_TSM_STATS_RSP msg back to LIM. 3872 * 3873 * Return: QDF status 3874 */ wma_process_tsm_stats_req(tp_wma_handle wma_handler,void * pTsmStatsMsg)3875 QDF_STATUS wma_process_tsm_stats_req(tp_wma_handle wma_handler, 3876 void *pTsmStatsMsg) 3877 { 3878 uint8_t counter; 3879 uint32_t queue_delay_microsec = 0; 3880 uint32_t tx_delay_microsec = 0; 3881 uint16_t packet_count = 0; 3882 uint16_t packet_loss_count = 0; 3883 tpAniTrafStrmMetrics pTsmMetric = NULL; 3884 tpAniGetTsmStatsReq pStats = (tpAniGetTsmStatsReq) pTsmStatsMsg; 3885 tpAniGetTsmStatsRsp pTsmRspParams = NULL; 3886 int tid = pStats->tid; 3887 /* 3888 * The number of histrogram bin report by data path api are different 3889 * than required by TSM, hence different (6) size array used 3890 */ 3891 uint16_t bin_values[QCA_TX_DELAY_HIST_REPORT_BINS] = { 0, }; 3892 void *soc = cds_get_context(QDF_MODULE_ID_SOC); 3893 3894 /* get required values from data path APIs */ 3895 cdp_tx_delay(soc, 3896 WMI_PDEV_ID_SOC, 3897 &queue_delay_microsec, 3898 &tx_delay_microsec, tid); 3899 cdp_tx_delay_hist(soc, 3900 WMI_PDEV_ID_SOC, 3901 bin_values, tid); 3902 cdp_tx_packet_count(soc, 3903 WMI_PDEV_ID_SOC, 3904 &packet_count, 3905 &packet_loss_count, tid); 3906 3907 pTsmRspParams = qdf_mem_malloc(sizeof(*pTsmRspParams)); 3908 if (!pTsmRspParams) { 3909 QDF_ASSERT(0); 3910 qdf_mem_free(pTsmStatsMsg); 3911 return QDF_STATUS_E_NOMEM; 3912 } 3913 3914 qdf_copy_macaddr(&pTsmRspParams->bssid, &pStats->bssId); 3915 pTsmRspParams->rc = QDF_STATUS_E_FAILURE; 3916 pTsmRspParams->tsmStatsReq = pStats; 3917 pTsmMetric = &pTsmRspParams->tsmMetrics; 3918 /* populate pTsmMetric */ 3919 pTsmMetric->UplinkPktQueueDly = queue_delay_microsec; 3920 /* store only required number of bin values */ 3921 for (counter = 0; counter < TSM_DELAY_HISTROGRAM_BINS; counter++) { 3922 pTsmMetric->UplinkPktQueueDlyHist[counter] = 3923 bin_values[counter]; 3924 } 3925 pTsmMetric->UplinkPktTxDly = tx_delay_microsec; 3926 pTsmMetric->UplinkPktLoss = packet_loss_count; 3927 pTsmMetric->UplinkPktCount = packet_count; 3928 3929 /* 3930 * No need to populate roaming delay and roaming count as they are 3931 * being populated just before sending IAPP frame out 3932 */ 3933 /* post this message to LIM/PE */ 3934 wma_send_msg(wma_handler, WMA_TSM_STATS_RSP, (void *)pTsmRspParams, 0); 3935 return QDF_STATUS_SUCCESS; 3936 } 3937 3938 #endif /* FEATURE_WLAN_ESE */ 3939 3940 /** 3941 * wma_process_mcbc_set_filter_req() - process mcbc set filter request 3942 * @wma_handle: wma handle 3943 * @mcbc_param: mcbc params 3944 * 3945 * Return: QDF status 3946 */ wma_process_mcbc_set_filter_req(tp_wma_handle wma_handle,tSirRcvFltMcAddrList * mcbc_param)3947 QDF_STATUS wma_process_mcbc_set_filter_req(tp_wma_handle wma_handle, 3948 tSirRcvFltMcAddrList *mcbc_param) 3949 { 3950 return QDF_STATUS_SUCCESS; 3951 } 3952 3953 /** 3954 * wma_process_add_periodic_tx_ptrn_ind() - add periodic tx pattern 3955 * @handle: wma handle 3956 * @pattern: tx pattern params 3957 * 3958 * Return: QDF status 3959 */ wma_process_add_periodic_tx_ptrn_ind(WMA_HANDLE handle,tSirAddPeriodicTxPtrn * pattern)3960 QDF_STATUS wma_process_add_periodic_tx_ptrn_ind(WMA_HANDLE handle, 3961 tSirAddPeriodicTxPtrn *pattern) 3962 { 3963 tp_wma_handle wma_handle = (tp_wma_handle) handle; 3964 struct periodic_tx_pattern *params_ptr; 3965 uint8_t vdev_id; 3966 QDF_STATUS status; 3967 struct wmi_unified *wmi_handle; 3968 3969 if (wma_validate_handle(wma_handle)) 3970 return QDF_STATUS_E_INVAL; 3971 3972 wmi_handle = wma_handle->wmi_handle; 3973 if (wmi_validate_handle(wmi_handle)) 3974 return QDF_STATUS_E_INVAL; 3975 3976 if (wma_find_vdev_id_by_addr(wma_handle, 3977 pattern->mac_address.bytes, 3978 &vdev_id)) { 3979 wma_err("Failed to find vdev id for "QDF_MAC_ADDR_FMT, 3980 QDF_MAC_ADDR_REF(pattern->mac_address.bytes)); 3981 return QDF_STATUS_E_INVAL; 3982 } 3983 3984 params_ptr = qdf_mem_malloc(sizeof(*params_ptr)); 3985 if (!params_ptr) 3986 return QDF_STATUS_E_NOMEM; 3987 3988 params_ptr->ucPtrnId = pattern->ucPtrnId; 3989 params_ptr->ucPtrnSize = pattern->ucPtrnSize; 3990 params_ptr->usPtrnIntervalMs = pattern->usPtrnIntervalMs; 3991 qdf_mem_copy(¶ms_ptr->mac_address, &pattern->mac_address, 3992 sizeof(struct qdf_mac_addr)); 3993 qdf_mem_copy(params_ptr->ucPattern, pattern->ucPattern, 3994 params_ptr->ucPtrnSize); 3995 3996 status = wmi_unified_process_add_periodic_tx_ptrn_cmd( 3997 wmi_handle, params_ptr, vdev_id); 3998 3999 qdf_mem_free(params_ptr); 4000 return status; 4001 } 4002 4003 /** 4004 * wma_process_del_periodic_tx_ptrn_ind - del periodic tx ptrn 4005 * @handle: wma handle 4006 * @pDelPeriodicTxPtrnParams: tx ptrn params 4007 * 4008 * Return: QDF status 4009 */ wma_process_del_periodic_tx_ptrn_ind(WMA_HANDLE handle,tSirDelPeriodicTxPtrn * pDelPeriodicTxPtrnParams)4010 QDF_STATUS wma_process_del_periodic_tx_ptrn_ind(WMA_HANDLE handle, 4011 tSirDelPeriodicTxPtrn * 4012 pDelPeriodicTxPtrnParams) 4013 { 4014 tp_wma_handle wma_handle = (tp_wma_handle) handle; 4015 uint8_t vdev_id; 4016 struct wmi_unified *wmi_handle; 4017 4018 if (wma_validate_handle(wma_handle)) 4019 return QDF_STATUS_E_INVAL; 4020 4021 wmi_handle = wma_handle->wmi_handle; 4022 if (wmi_validate_handle(wmi_handle)) 4023 return QDF_STATUS_E_INVAL; 4024 4025 if (wma_find_vdev_id_by_addr( 4026 wma_handle, 4027 pDelPeriodicTxPtrnParams->mac_address.bytes, 4028 &vdev_id)) { 4029 wma_err("Failed to find vdev id for "QDF_MAC_ADDR_FMT, 4030 QDF_MAC_ADDR_REF(pDelPeriodicTxPtrnParams->mac_address.bytes)); 4031 return QDF_STATUS_E_INVAL; 4032 } 4033 4034 return wmi_unified_process_del_periodic_tx_ptrn_cmd( 4035 wmi_handle, vdev_id, 4036 pDelPeriodicTxPtrnParams->ucPtrnId); 4037 } 4038 4039 #ifdef WLAN_FEATURE_STATS_EXT 4040 #ifdef WLAN_FEATURE_11BE_MLO 4041 /* 4042 * wma_stats_ext_req_vdev_id_bitmap() -API to calculate connected links bitmap 4043 * in case of MLO. 4044 * psoc: psoc common object 4045 * vdev_id: vdev_id for the stats ext request 4046 * bitmap: connected links bitmap 4047 * 4048 * Return None 4049 */ wma_stats_ext_req_vdev_id_bitmap(struct wlan_objmgr_psoc * psoc,uint32_t vdev_id,uint32_t * bitmap)4050 static void wma_stats_ext_req_vdev_id_bitmap(struct wlan_objmgr_psoc *psoc, 4051 uint32_t vdev_id, uint32_t *bitmap) 4052 { 4053 struct wlan_objmgr_vdev *vdev, *link_vdev; 4054 struct wlan_mlo_dev_context *mlo_dev_ctx; 4055 uint32_t i, connected_links_bitmap = 0; 4056 uint8_t connected_vdev_id; 4057 4058 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id, 4059 WLAN_LEGACY_WMA_ID); 4060 if (!vdev) { 4061 wma_err("vdev object is NULL for vdev_id %d", vdev_id); 4062 return; 4063 } 4064 4065 mlo_dev_ctx = vdev->mlo_dev_ctx; 4066 if (!mlo_dev_ctx) 4067 goto end; 4068 4069 for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) { 4070 link_vdev = mlo_dev_ctx->wlan_vdev_list[i]; 4071 if (!link_vdev) 4072 continue; 4073 4074 connected_vdev_id = wlan_vdev_get_id(link_vdev); 4075 if (wlan_cm_is_vdev_connected(link_vdev)) 4076 connected_links_bitmap |= BIT(connected_vdev_id); 4077 } 4078 4079 wma_debug("mlo connected links bitmap[0x%x]", connected_links_bitmap); 4080 *bitmap = connected_links_bitmap; 4081 4082 end: 4083 wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_WMA_ID); 4084 } 4085 #else wma_stats_ext_req_vdev_id_bitmap(struct wlan_objmgr_psoc * psoc,uint32_t vdev_id,uint32_t * bitmap)4086 static void wma_stats_ext_req_vdev_id_bitmap(struct wlan_objmgr_psoc *psoc, 4087 uint32_t vdev_id, uint32_t *bitmap) 4088 { 4089 *bitmap = 0; 4090 } 4091 #endif 4092 wma_stats_ext_req(void * wma_ptr,tpStatsExtRequest preq)4093 QDF_STATUS wma_stats_ext_req(void *wma_ptr, tpStatsExtRequest preq) 4094 { 4095 tp_wma_handle wma = (tp_wma_handle) wma_ptr; 4096 struct stats_ext_params *params; 4097 size_t params_len; 4098 QDF_STATUS status; 4099 4100 if (!wma) { 4101 wma_err("wma handle is NULL"); 4102 return QDF_STATUS_E_FAILURE; 4103 } 4104 4105 params_len = sizeof(*params) + preq->request_data_len; 4106 params = qdf_mem_malloc(params_len); 4107 if (!params) 4108 return QDF_STATUS_E_NOMEM; 4109 4110 params->vdev_id = preq->vdev_id; 4111 params->request_data_len = preq->request_data_len; 4112 if (preq->request_data_len > 0) 4113 qdf_mem_copy(params->request_data, preq->request_data, 4114 params->request_data_len); 4115 4116 wma_stats_ext_req_vdev_id_bitmap(wma->psoc, params->vdev_id, 4117 ¶ms->vdev_id_bitmap); 4118 4119 status = wmi_unified_stats_ext_req_cmd(wma->wmi_handle, params); 4120 qdf_mem_free(params); 4121 4122 return status; 4123 } 4124 4125 #endif /* WLAN_FEATURE_STATS_EXT */ 4126 4127 #ifdef WLAN_FEATURE_EXTWOW_SUPPORT 4128 /** 4129 * wma_send_status_of_ext_wow() - send ext wow status to SME 4130 * @wma: wma handle 4131 * @status: status 4132 * 4133 * Return: none 4134 */ wma_send_status_of_ext_wow(tp_wma_handle wma,bool status)4135 static void wma_send_status_of_ext_wow(tp_wma_handle wma, bool status) 4136 { 4137 tSirReadyToExtWoWInd *ready_to_extwow; 4138 QDF_STATUS vstatus; 4139 struct scheduler_msg message = {0}; 4140 uint8_t len; 4141 4142 wma_debug("Posting ready to suspend indication to umac"); 4143 4144 len = sizeof(tSirReadyToExtWoWInd); 4145 ready_to_extwow = qdf_mem_malloc(len); 4146 if (!ready_to_extwow) 4147 return; 4148 4149 ready_to_extwow->mesgType = eWNI_SME_READY_TO_EXTWOW_IND; 4150 ready_to_extwow->mesgLen = len; 4151 ready_to_extwow->status = status; 4152 4153 message.type = eWNI_SME_READY_TO_EXTWOW_IND; 4154 message.bodyptr = (void *)ready_to_extwow; 4155 message.bodyval = 0; 4156 4157 vstatus = scheduler_post_message(QDF_MODULE_ID_WMA, 4158 QDF_MODULE_ID_SME, 4159 QDF_MODULE_ID_SME, &message); 4160 if (vstatus != QDF_STATUS_SUCCESS) 4161 qdf_mem_free(ready_to_extwow); 4162 } 4163 4164 /** 4165 * wma_enable_ext_wow() - enable ext wow in fw 4166 * @wma: wma handle 4167 * @params: ext wow params 4168 * 4169 * Return:0 for success or error code 4170 */ wma_enable_ext_wow(tp_wma_handle wma,tpSirExtWoWParams params)4171 QDF_STATUS wma_enable_ext_wow(tp_wma_handle wma, tpSirExtWoWParams params) 4172 { 4173 struct ext_wow_params wow_params = {0}; 4174 QDF_STATUS status; 4175 4176 if (!wma) { 4177 wma_err("wma handle is NULL"); 4178 return QDF_STATUS_E_FAILURE; 4179 } 4180 4181 wow_params.vdev_id = params->vdev_id; 4182 wow_params.type = (enum wmi_ext_wow_type) params->type; 4183 wow_params.wakeup_pin_num = params->wakeup_pin_num; 4184 4185 status = wmi_unified_enable_ext_wow_cmd(wma->wmi_handle, 4186 &wow_params); 4187 if (QDF_IS_STATUS_ERROR(status)) 4188 return status; 4189 4190 wma_send_status_of_ext_wow(wma, true); 4191 return status; 4192 4193 } 4194 4195 /** 4196 * wma_set_app_type1_params_in_fw() - set app type1 params in fw 4197 * @wma: wma handle 4198 * @appType1Params: app type1 params 4199 * 4200 * Return: QDF status 4201 */ wma_set_app_type1_params_in_fw(tp_wma_handle wma,tpSirAppType1Params appType1Params)4202 int wma_set_app_type1_params_in_fw(tp_wma_handle wma, 4203 tpSirAppType1Params appType1Params) 4204 { 4205 int ret; 4206 4207 ret = wmi_unified_app_type1_params_in_fw_cmd(wma->wmi_handle, 4208 (struct app_type1_params *)appType1Params); 4209 if (ret) { 4210 wma_err("Failed to set APP TYPE1 PARAMS"); 4211 return QDF_STATUS_E_FAILURE; 4212 } 4213 4214 return QDF_STATUS_SUCCESS; 4215 } 4216 4217 /** 4218 * wma_set_app_type2_params_in_fw() - set app type2 params in fw 4219 * @wma: wma handle 4220 * @appType2Params: app type2 params 4221 * 4222 * Return: QDF status 4223 */ wma_set_app_type2_params_in_fw(tp_wma_handle wma,tpSirAppType2Params appType2Params)4224 QDF_STATUS wma_set_app_type2_params_in_fw(tp_wma_handle wma, 4225 tpSirAppType2Params appType2Params) 4226 { 4227 struct app_type2_params params = {0}; 4228 4229 if (!wma) { 4230 wma_err("wma handle is NULL"); 4231 return QDF_STATUS_E_FAILURE; 4232 } 4233 4234 params.vdev_id = appType2Params->vdev_id; 4235 params.rc4_key_len = appType2Params->rc4_key_len; 4236 qdf_mem_copy(params.rc4_key, appType2Params->rc4_key, 16); 4237 params.ip_id = appType2Params->ip_id; 4238 params.ip_device_ip = appType2Params->ip_device_ip; 4239 params.ip_server_ip = appType2Params->ip_server_ip; 4240 params.tcp_src_port = appType2Params->tcp_src_port; 4241 params.tcp_dst_port = appType2Params->tcp_dst_port; 4242 params.tcp_seq = appType2Params->tcp_seq; 4243 params.tcp_ack_seq = appType2Params->tcp_ack_seq; 4244 params.keepalive_init = appType2Params->keepalive_init; 4245 params.keepalive_min = appType2Params->keepalive_min; 4246 params.keepalive_max = appType2Params->keepalive_max; 4247 params.keepalive_inc = appType2Params->keepalive_inc; 4248 params.tcp_tx_timeout_val = appType2Params->tcp_tx_timeout_val; 4249 params.tcp_rx_timeout_val = appType2Params->tcp_rx_timeout_val; 4250 qdf_mem_copy(¶ms.gateway_mac, &appType2Params->gateway_mac, 4251 sizeof(struct qdf_mac_addr)); 4252 4253 return wmi_unified_set_app_type2_params_in_fw_cmd(wma->wmi_handle, 4254 ¶ms); 4255 } 4256 #endif /* WLAN_FEATURE_EXTWOW_SUPPORT */ 4257 4258 #ifdef FEATURE_WLAN_AUTO_SHUTDOWN 4259 /** 4260 * wma_auto_shutdown_event_handler() - process auto shutdown timer trigger 4261 * @handle: wma handle 4262 * @event: event buffer 4263 * @len: buffer length 4264 * 4265 * Return: 0 for success or error code 4266 */ wma_auto_shutdown_event_handler(void * handle,uint8_t * event,uint32_t len)4267 int wma_auto_shutdown_event_handler(void *handle, uint8_t *event, 4268 uint32_t len) 4269 { 4270 wmi_host_auto_shutdown_event_fixed_param *wmi_auto_sh_evt; 4271 WMI_HOST_AUTO_SHUTDOWN_EVENTID_param_tlvs *param_buf = 4272 (WMI_HOST_AUTO_SHUTDOWN_EVENTID_param_tlvs *) 4273 event; 4274 4275 if (!param_buf || !param_buf->fixed_param) { 4276 wma_err("Invalid Auto shutdown timer evt"); 4277 return -EINVAL; 4278 } 4279 4280 wmi_auto_sh_evt = param_buf->fixed_param; 4281 4282 if (wmi_auto_sh_evt->shutdown_reason 4283 != WMI_HOST_AUTO_SHUTDOWN_REASON_TIMER_EXPIRY) { 4284 wma_err("Invalid Auto shutdown timer evt"); 4285 return -EINVAL; 4286 } 4287 4288 wma_debug("Auto Shutdown Evt: %d", wmi_auto_sh_evt->shutdown_reason); 4289 return wma_wake_reason_auto_shutdown(); 4290 } 4291 4292 QDF_STATUS wma_set_auto_shutdown_timer_req(tp_wma_handle wma_handle,struct auto_shutdown_cmd * auto_sh_cmd)4293 wma_set_auto_shutdown_timer_req(tp_wma_handle wma_handle, 4294 struct auto_shutdown_cmd *auto_sh_cmd) 4295 { 4296 if (!auto_sh_cmd) { 4297 wma_err("Invalid Autoshutdown cfg cmd"); 4298 return QDF_STATUS_E_FAILURE; 4299 } 4300 4301 return wmi_unified_set_auto_shutdown_timer_cmd(wma_handle->wmi_handle, 4302 auto_sh_cmd->timer_val); 4303 } 4304 #endif /* FEATURE_WLAN_AUTO_SHUTDOWN */ 4305 4306 #ifdef DHCP_SERVER_OFFLOAD 4307 QDF_STATUS wma_process_dhcpserver_offload(tp_wma_handle wma_handle,struct dhcp_offload_info_params * params)4308 wma_process_dhcpserver_offload(tp_wma_handle wma_handle, 4309 struct dhcp_offload_info_params *params) 4310 { 4311 QDF_STATUS status; 4312 wmi_unified_t wmi_handle; 4313 4314 if (!wma_handle) { 4315 wma_err("wma handle is NULL"); 4316 return QDF_STATUS_E_FAILURE; 4317 } 4318 4319 wmi_handle = wma_handle->wmi_handle; 4320 status = wmi_unified_process_dhcpserver_offload_cmd(wmi_handle, 4321 params); 4322 wma_debug("Set dhcp server offload to vdev %d status %d", 4323 params->vdev_id, status); 4324 4325 return status; 4326 } 4327 #endif /* DHCP_SERVER_OFFLOAD */ 4328 4329 #ifdef WLAN_FEATURE_GPIO_LED_FLASHING 4330 /** 4331 * wma_set_led_flashing() - set led flashing in fw 4332 * @wma_handle: wma handle 4333 * @flashing: flashing request 4334 * 4335 * Return: QDF status 4336 */ wma_set_led_flashing(tp_wma_handle wma_handle,struct flashing_req_params * flashing)4337 QDF_STATUS wma_set_led_flashing(tp_wma_handle wma_handle, 4338 struct flashing_req_params *flashing) 4339 { 4340 QDF_STATUS status; 4341 struct wmi_unified *wmi_handle; 4342 4343 if (wma_validate_handle(wma_handle)) 4344 return QDF_STATUS_E_INVAL; 4345 4346 wmi_handle = wma_handle->wmi_handle; 4347 if (wmi_validate_handle(wmi_handle)) 4348 return QDF_STATUS_E_INVAL; 4349 4350 if (!flashing) { 4351 wma_err("invalid parameter: flashing"); 4352 return QDF_STATUS_E_INVAL; 4353 } 4354 status = wmi_unified_set_led_flashing_cmd(wmi_handle, flashing); 4355 return status; 4356 } 4357 #endif /* WLAN_FEATURE_GPIO_LED_FLASHING */ 4358 wma_sar_rsp_evt_handler(ol_scn_t handle,uint8_t * event,uint32_t len)4359 int wma_sar_rsp_evt_handler(ol_scn_t handle, uint8_t *event, uint32_t len) 4360 { 4361 tp_wma_handle wma_handle; 4362 wmi_unified_t wmi_handle; 4363 QDF_STATUS status; 4364 4365 wma_debug("handle:%pK event:%pK len:%u", handle, event, len); 4366 4367 wma_handle = handle; 4368 if (wma_validate_handle(wma_handle)) 4369 return QDF_STATUS_E_INVAL; 4370 4371 wmi_handle = wma_handle->wmi_handle; 4372 if (wmi_validate_handle(wmi_handle)) 4373 return QDF_STATUS_E_INVAL; 4374 4375 status = wmi_unified_extract_sar2_result_event(wmi_handle, 4376 event, len); 4377 if (QDF_IS_STATUS_ERROR(status)) { 4378 wma_err("Event extract failure: %d", status); 4379 return -EINVAL; 4380 } 4381 4382 return 0; 4383 } 4384 4385 #ifdef FEATURE_WLAN_CH_AVOID 4386 /** 4387 * wma_process_ch_avoid_update_req() - handles channel avoid update request 4388 * @wma_handle: wma handle 4389 * @ch_avoid_update_req: channel avoid update params 4390 * 4391 * Return: QDF status 4392 */ wma_process_ch_avoid_update_req(tp_wma_handle wma_handle,tSirChAvoidUpdateReq * ch_avoid_update_req)4393 QDF_STATUS wma_process_ch_avoid_update_req(tp_wma_handle wma_handle, 4394 tSirChAvoidUpdateReq * 4395 ch_avoid_update_req) 4396 { 4397 QDF_STATUS status; 4398 struct wmi_unified *wmi_handle; 4399 4400 if (wma_validate_handle(wma_handle)) 4401 return QDF_STATUS_E_FAILURE; 4402 4403 wmi_handle = wma_handle->wmi_handle; 4404 if (wmi_validate_handle(wmi_handle)) 4405 return QDF_STATUS_E_FAILURE; 4406 4407 if (!ch_avoid_update_req) { 4408 wma_err("ch_avoid_update_req is NULL"); 4409 return QDF_STATUS_E_FAILURE; 4410 } 4411 4412 wma_debug("WMA --> WMI_CHAN_AVOID_UPDATE"); 4413 4414 status = wmi_unified_process_ch_avoid_update_cmd(wmi_handle); 4415 if (QDF_IS_STATUS_ERROR(status)) 4416 return status; 4417 4418 wma_debug("WMA --> WMI_CHAN_AVOID_UPDATE sent through WMI"); 4419 return status; 4420 } 4421 #endif 4422 wma_send_regdomain_info_to_fw(uint32_t reg_dmn,uint16_t regdmn2G,uint16_t regdmn5G,uint8_t ctl2G,uint8_t ctl5G)4423 void wma_send_regdomain_info_to_fw(uint32_t reg_dmn, uint16_t regdmn2G, 4424 uint16_t regdmn5G, uint8_t ctl2G, 4425 uint8_t ctl5G) 4426 { 4427 tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA); 4428 int32_t cck_mask_val = 0; 4429 struct pdev_params pdev_param = {0}; 4430 QDF_STATUS ret = QDF_STATUS_SUCCESS; 4431 QDF_STATUS status = QDF_STATUS_SUCCESS; 4432 4433 wma_debug("reg_dmn: %d regdmn2g: %d regdmn5g :%d ctl2g: %d ctl5g: %d", 4434 reg_dmn, regdmn2G, regdmn5G, ctl2G, ctl5G); 4435 4436 if (!wma) 4437 return; 4438 4439 status = wmi_unified_send_regdomain_info_to_fw_cmd(wma->wmi_handle, 4440 reg_dmn, regdmn2G, regdmn5G, ctl2G, ctl5G); 4441 if (status == QDF_STATUS_E_NOMEM) 4442 return; 4443 4444 if ((((reg_dmn & ~CTRY_FLAG) == CTRY_JAPAN15) || 4445 ((reg_dmn & ~CTRY_FLAG) == CTRY_KOREA_ROC)) && 4446 (true == wma->tx_chain_mask_cck)) 4447 cck_mask_val = 1; 4448 4449 cck_mask_val |= (wma->self_gen_frm_pwr << 16); 4450 pdev_param.param_id = wmi_pdev_param_tx_chain_mask_cck; 4451 pdev_param.param_value = cck_mask_val; 4452 ret = wmi_unified_pdev_param_send(wma->wmi_handle, 4453 &pdev_param, 4454 WMA_WILDCARD_PDEV_ID); 4455 4456 if (QDF_IS_STATUS_ERROR(ret)) 4457 wma_err("failed to set PDEV tx_chain_mask_cck %d", ret); 4458 } 4459 4460 #ifdef FEATURE_WLAN_TDLS 4461 /** 4462 * wma_tdls_event_handler() - handle TDLS event 4463 * @handle: wma handle 4464 * @event: event buffer 4465 * @len: buffer length 4466 * 4467 * Return: 0 for success or error code 4468 */ wma_tdls_event_handler(void * handle,uint8_t * event,uint32_t len)4469 int wma_tdls_event_handler(void *handle, uint8_t *event, uint32_t len) 4470 { 4471 /* TODO update with target rx ops */ 4472 return 0; 4473 } 4474 4475 /** 4476 * wma_update_tdls_peer_state() - update TDLS peer state 4477 * @handle: wma handle 4478 * @peer_state: TDLS peer state params 4479 * 4480 * Return: 0 for success or error code 4481 */ wma_update_tdls_peer_state(WMA_HANDLE handle,struct tdls_peer_update_state * peer_state)4482 int wma_update_tdls_peer_state(WMA_HANDLE handle, 4483 struct tdls_peer_update_state *peer_state) 4484 { 4485 tp_wma_handle wma_handle = (tp_wma_handle) handle; 4486 uint32_t i; 4487 void *soc = cds_get_context(QDF_MODULE_ID_SOC); 4488 struct tdls_peer_params *peer_cap; 4489 int ret = 0; 4490 uint32_t *ch_mhz = NULL; 4491 size_t ch_mhz_len; 4492 bool restore_last_peer = false; 4493 QDF_STATUS qdf_status; 4494 struct wmi_unified *wmi_handle; 4495 4496 if (wma_validate_handle(wma_handle)) { 4497 ret = -EINVAL; 4498 goto end_tdls_peer_state; 4499 } 4500 4501 wmi_handle = wma_handle->wmi_handle; 4502 if (wmi_validate_handle(wmi_handle)) { 4503 ret = -EINVAL; 4504 goto end_tdls_peer_state; 4505 } 4506 4507 if (!soc) { 4508 ret = -EINVAL; 4509 goto end_tdls_peer_state; 4510 } 4511 4512 if (wlan_cm_is_roam_sync_in_progress(wma_handle->psoc, 4513 peer_state->vdev_id)) { 4514 wma_err("roaming in progress, reject peer update cmd!"); 4515 ret = -EPERM; 4516 goto end_tdls_peer_state; 4517 } 4518 4519 4520 if (!wma_objmgr_peer_exist(wma_handle, 4521 peer_state->peer_macaddr, NULL)) { 4522 wma_err("peer:" QDF_MAC_ADDR_FMT "doesn't exist", 4523 QDF_MAC_ADDR_REF(peer_state->peer_macaddr)); 4524 ret = -EINVAL; 4525 goto end_tdls_peer_state; 4526 } 4527 4528 peer_cap = &peer_state->peer_cap; 4529 4530 /* peer capability info is valid only when peer state is connected */ 4531 if (TDLS_PEER_STATE_CONNECTED != peer_state->peer_state) 4532 qdf_mem_zero(peer_cap, sizeof(*peer_cap)); 4533 4534 if (peer_cap->peer_chanlen) { 4535 ch_mhz_len = sizeof(*ch_mhz) * peer_cap->peer_chanlen; 4536 ch_mhz = qdf_mem_malloc(ch_mhz_len); 4537 if (!ch_mhz) { 4538 ret = -ENOMEM; 4539 goto end_tdls_peer_state; 4540 } 4541 4542 for (i = 0; i < peer_cap->peer_chanlen; ++i) 4543 ch_mhz[i] = peer_cap->peer_chan[i].ch_freq; 4544 } 4545 4546 cdp_peer_set_tdls_offchan_enabled(soc, peer_state->vdev_id, 4547 peer_state->peer_macaddr, 4548 !!peer_cap->peer_off_chan_support); 4549 4550 if (wmi_unified_update_tdls_peer_state_cmd(wma_handle->wmi_handle, 4551 peer_state, 4552 ch_mhz)) { 4553 wma_err("failed to send tdls peer update state command"); 4554 ret = -EIO; 4555 /* Fall through to delete TDLS peer for teardown */ 4556 } 4557 4558 /* in case of teardown, remove peer from fw */ 4559 if (TDLS_PEER_STATE_TEARDOWN == peer_state->peer_state) { 4560 restore_last_peer = cdp_peer_is_vdev_restore_last_peer( 4561 soc, 4562 peer_state->vdev_id, 4563 peer_state->peer_macaddr); 4564 4565 wma_debug("calling wma_remove_peer for peer " QDF_MAC_ADDR_FMT 4566 " vdevId: %d", 4567 QDF_MAC_ADDR_REF(peer_state->peer_macaddr), 4568 peer_state->vdev_id); 4569 qdf_status = wma_remove_peer(wma_handle, 4570 peer_state->peer_macaddr, 4571 peer_state->vdev_id, false); 4572 if (QDF_IS_STATUS_ERROR(qdf_status)) { 4573 wma_err("wma_remove_peer failed"); 4574 ret = -EINVAL; 4575 } 4576 cdp_peer_update_last_real_peer(soc, WMI_PDEV_ID_SOC, 4577 peer_state->vdev_id, 4578 restore_last_peer); 4579 } 4580 4581 if (TDLS_PEER_STATE_CONNECTED == peer_state->peer_state) { 4582 cdp_peer_state_update(soc, peer_state->peer_macaddr, 4583 OL_TXRX_PEER_STATE_AUTH); 4584 } 4585 4586 end_tdls_peer_state: 4587 if (ch_mhz) 4588 qdf_mem_free(ch_mhz); 4589 if (peer_state) 4590 qdf_mem_free(peer_state); 4591 return ret; 4592 } 4593 #endif /* FEATURE_WLAN_TDLS */ 4594 4595 /* 4596 * wma_process_cfg_action_frm_tb_ppdu() - action frame TB PPDU cfg to firmware 4597 * @wma: Pointer to WMA handle 4598 * @cfg_info: Pointer for cfg info 4599 * 4600 * Return: QDF_STATUS_SUCCESS for success otherwise failure 4601 * 4602 */ wma_process_cfg_action_frm_tb_ppdu(tp_wma_handle wma,struct cfg_action_frm_tb_ppdu * cfg_info)4603 QDF_STATUS wma_process_cfg_action_frm_tb_ppdu(tp_wma_handle wma, 4604 struct cfg_action_frm_tb_ppdu *cfg_info) 4605 { 4606 struct cfg_action_frm_tb_ppdu_param cmd = {0}; 4607 4608 if (wma_validate_handle(wma)) 4609 return QDF_STATUS_E_FAILURE; 4610 4611 cmd.frm_len = cfg_info->frm_len; 4612 cmd.cfg = cfg_info->cfg; 4613 cmd.data = cfg_info->data; 4614 4615 wma_debug("cfg: %d, frm_len: %d", cfg_info->cfg, cfg_info->frm_len); 4616 4617 return wmi_unified_cfg_action_frm_tb_ppdu_cmd(wma->wmi_handle, &cmd); 4618 } 4619 4620 4621 /* 4622 * wma_process_set_ie_info() - Function to send IE info to firmware 4623 * @wma: Pointer to WMA handle 4624 * @ie_data: Pointer for ie data 4625 * 4626 * This function sends IE information to firmware 4627 * 4628 * Return: QDF_STATUS_SUCCESS for success otherwise failure 4629 * 4630 */ wma_process_set_ie_info(tp_wma_handle wma,struct vdev_ie_info * ie_info)4631 QDF_STATUS wma_process_set_ie_info(tp_wma_handle wma, 4632 struct vdev_ie_info *ie_info) 4633 { 4634 struct wma_txrx_node *interface; 4635 struct vdev_ie_info_param cmd = {0}; 4636 4637 if (!ie_info || !wma) { 4638 wma_err("input pointer is NULL"); 4639 return QDF_STATUS_E_FAILURE; 4640 } 4641 4642 /* Validate the input */ 4643 if (ie_info->length <= 0) { 4644 wma_err("Invalid IE length"); 4645 return QDF_STATUS_E_INVAL; 4646 } 4647 4648 if (!wma_is_vdev_valid(ie_info->vdev_id)) { 4649 wma_err("vdev_id: %d is not active", ie_info->vdev_id); 4650 return QDF_STATUS_E_INVAL; 4651 } 4652 4653 interface = &wma->interfaces[ie_info->vdev_id]; 4654 cmd.vdev_id = ie_info->vdev_id; 4655 cmd.ie_id = ie_info->ie_id; 4656 cmd.length = ie_info->length; 4657 cmd.band = ie_info->band; 4658 cmd.data = ie_info->data; 4659 cmd.ie_source = WMA_SET_VDEV_IE_SOURCE_HOST; 4660 4661 wma_debug("vdev id: %d, ie_id: %d, band: %d, len: %d", 4662 ie_info->vdev_id, ie_info->ie_id, ie_info->band, 4663 ie_info->length); 4664 4665 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_WMA, QDF_TRACE_LEVEL_DEBUG, 4666 ie_info->data, ie_info->length); 4667 4668 return wmi_unified_process_set_ie_info_cmd(wma->wmi_handle, &cmd); 4669 } 4670 4671 #ifdef FEATURE_WLAN_APF 4672 /** 4673 * wma_get_apf_caps_event_handler() - Event handler for get apf capability 4674 * @handle: WMA global handle 4675 * @cmd_param_info: command event data 4676 * @len: Length of @cmd_param_info 4677 * 4678 * Return: 0 on Success or Errno on failure 4679 */ wma_get_apf_caps_event_handler(void * handle,u_int8_t * cmd_param_info,u_int32_t len)4680 int wma_get_apf_caps_event_handler(void *handle, u_int8_t *cmd_param_info, 4681 u_int32_t len) 4682 { 4683 WMI_BPF_CAPABILIY_INFO_EVENTID_param_tlvs *param_buf; 4684 wmi_bpf_capability_info_evt_fixed_param *event; 4685 struct sir_apf_get_offload *apf_get_offload; 4686 struct mac_context *pmac = (struct mac_context *)cds_get_context( 4687 QDF_MODULE_ID_PE); 4688 4689 if (!pmac) 4690 return -EINVAL; 4691 4692 if (!pmac->sme.apf_get_offload_cb) { 4693 wma_err("Callback not registered"); 4694 return -EINVAL; 4695 } 4696 4697 param_buf = (WMI_BPF_CAPABILIY_INFO_EVENTID_param_tlvs *)cmd_param_info; 4698 event = param_buf->fixed_param; 4699 apf_get_offload = qdf_mem_malloc(sizeof(*apf_get_offload)); 4700 if (!apf_get_offload) 4701 return -ENOMEM; 4702 4703 apf_get_offload->apf_version = event->bpf_version; 4704 apf_get_offload->max_apf_filters = event->max_bpf_filters; 4705 apf_get_offload->max_bytes_for_apf_inst = 4706 event->max_bytes_for_bpf_inst; 4707 wma_debug("APF capabilities version: %d max apf filter size: %d", 4708 apf_get_offload->apf_version, 4709 apf_get_offload->max_bytes_for_apf_inst); 4710 4711 wma_debug("sending apf capabilities event to hdd"); 4712 pmac->sme.apf_get_offload_cb(pmac->sme.apf_get_offload_context, 4713 apf_get_offload); 4714 qdf_mem_free(apf_get_offload); 4715 return 0; 4716 } 4717 wma_get_apf_capabilities(tp_wma_handle wma)4718 QDF_STATUS wma_get_apf_capabilities(tp_wma_handle wma) 4719 { 4720 QDF_STATUS status = QDF_STATUS_SUCCESS; 4721 wmi_bpf_get_capability_cmd_fixed_param *cmd; 4722 wmi_buf_t wmi_buf; 4723 uint32_t len; 4724 u_int8_t *buf_ptr; 4725 struct wmi_unified *wmi_handle; 4726 4727 if (wma_validate_handle(wma)) 4728 return QDF_STATUS_E_INVAL; 4729 4730 wmi_handle = wma->wmi_handle; 4731 if (wmi_validate_handle(wmi_handle)) 4732 return QDF_STATUS_E_INVAL; 4733 4734 if (!wmi_service_enabled(wmi_handle, wmi_service_apf_offload)) { 4735 wma_err("APF cababilities feature bit not enabled"); 4736 return QDF_STATUS_E_FAILURE; 4737 } 4738 4739 len = sizeof(*cmd); 4740 wmi_buf = wmi_buf_alloc(wmi_handle, len); 4741 if (!wmi_buf) 4742 return QDF_STATUS_E_NOMEM; 4743 4744 buf_ptr = (u_int8_t *) wmi_buf_data(wmi_buf); 4745 cmd = (wmi_bpf_get_capability_cmd_fixed_param *) buf_ptr; 4746 WMITLV_SET_HDR(&cmd->tlv_header, 4747 WMITLV_TAG_STRUC_wmi_bpf_get_capability_cmd_fixed_param, 4748 WMITLV_GET_STRUCT_TLVLEN( 4749 wmi_bpf_get_capability_cmd_fixed_param)); 4750 4751 if (wmi_unified_cmd_send(wmi_handle, wmi_buf, len, 4752 WMI_BPF_GET_CAPABILITY_CMDID)) { 4753 wmi_buf_free(wmi_buf); 4754 return QDF_STATUS_E_FAILURE; 4755 } 4756 return status; 4757 } 4758 wma_set_apf_instructions(tp_wma_handle wma,struct sir_apf_set_offload * apf_set_offload)4759 QDF_STATUS wma_set_apf_instructions(tp_wma_handle wma, 4760 struct sir_apf_set_offload *apf_set_offload) 4761 { 4762 wmi_bpf_set_vdev_instructions_cmd_fixed_param *cmd; 4763 wmi_buf_t wmi_buf; 4764 uint32_t len = 0, len_aligned = 0; 4765 u_int8_t *buf_ptr; 4766 struct wmi_unified *wmi_handle; 4767 4768 if (wma_validate_handle(wma)) 4769 return QDF_STATUS_E_INVAL; 4770 4771 wmi_handle = wma->wmi_handle; 4772 if (wmi_validate_handle(wmi_handle)) 4773 return QDF_STATUS_E_INVAL; 4774 4775 if (!wmi_service_enabled(wmi_handle, 4776 wmi_service_apf_offload)) { 4777 wma_err("APF offload feature Disabled"); 4778 return QDF_STATUS_E_NOSUPPORT; 4779 } 4780 4781 if (!apf_set_offload) { 4782 wma_err("Invalid APF instruction request"); 4783 return QDF_STATUS_E_INVAL; 4784 } 4785 4786 if (apf_set_offload->session_id >= wma->max_bssid) { 4787 wma_err("Invalid vdev_id: %d", apf_set_offload->session_id); 4788 return QDF_STATUS_E_INVAL; 4789 } 4790 4791 if (!wma_is_vdev_up(apf_set_offload->session_id)) { 4792 wma_err("vdev %d is not up skipping APF offload", 4793 apf_set_offload->session_id); 4794 return QDF_STATUS_E_INVAL; 4795 } 4796 4797 if (apf_set_offload->total_length) { 4798 len_aligned = roundup(apf_set_offload->current_length, 4799 sizeof(A_UINT32)); 4800 len = len_aligned + WMI_TLV_HDR_SIZE; 4801 } 4802 4803 len += sizeof(*cmd); 4804 wmi_buf = wmi_buf_alloc(wmi_handle, len); 4805 if (!wmi_buf) 4806 return QDF_STATUS_E_NOMEM; 4807 4808 buf_ptr = (u_int8_t *) wmi_buf_data(wmi_buf); 4809 cmd = (wmi_bpf_set_vdev_instructions_cmd_fixed_param *) buf_ptr; 4810 4811 WMITLV_SET_HDR(&cmd->tlv_header, 4812 WMITLV_TAG_STRUC_wmi_bpf_set_vdev_instructions_cmd_fixed_param, 4813 WMITLV_GET_STRUCT_TLVLEN( 4814 wmi_bpf_set_vdev_instructions_cmd_fixed_param)); 4815 cmd->vdev_id = apf_set_offload->session_id; 4816 cmd->filter_id = apf_set_offload->filter_id; 4817 cmd->total_length = apf_set_offload->total_length; 4818 cmd->current_offset = apf_set_offload->current_offset; 4819 cmd->current_length = apf_set_offload->current_length; 4820 4821 if (apf_set_offload->total_length) { 4822 buf_ptr += 4823 sizeof(wmi_bpf_set_vdev_instructions_cmd_fixed_param); 4824 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE, len_aligned); 4825 buf_ptr += WMI_TLV_HDR_SIZE; 4826 qdf_mem_copy(buf_ptr, apf_set_offload->program, 4827 apf_set_offload->current_length); 4828 } 4829 4830 if (wmi_unified_cmd_send(wmi_handle, wmi_buf, len, 4831 WMI_BPF_SET_VDEV_INSTRUCTIONS_CMDID)) { 4832 wmi_buf_free(wmi_buf); 4833 return QDF_STATUS_E_FAILURE; 4834 } 4835 wma_debug("APF offload enabled in fw"); 4836 4837 return QDF_STATUS_SUCCESS; 4838 } 4839 wma_send_apf_enable_cmd(WMA_HANDLE handle,uint8_t vdev_id,bool apf_enable)4840 QDF_STATUS wma_send_apf_enable_cmd(WMA_HANDLE handle, uint8_t vdev_id, 4841 bool apf_enable) 4842 { 4843 QDF_STATUS status = QDF_STATUS_SUCCESS; 4844 tp_wma_handle wma = (tp_wma_handle) handle; 4845 struct wmi_unified *wmi_handle; 4846 4847 if (!wma_is_vdev_valid(vdev_id)) 4848 return QDF_STATUS_E_INVAL; 4849 4850 if (wma_validate_handle(wma)) 4851 return QDF_STATUS_E_INVAL; 4852 4853 wmi_handle = wma->wmi_handle; 4854 if (wmi_validate_handle(wmi_handle)) 4855 return QDF_STATUS_E_INVAL; 4856 4857 if (!WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap, 4858 WMI_SERVICE_BPF_OFFLOAD)) { 4859 wma_err("APF cababilities feature bit not enabled"); 4860 return QDF_STATUS_E_FAILURE; 4861 } 4862 4863 status = wmi_unified_send_apf_enable_cmd(wmi_handle, vdev_id, 4864 apf_enable); 4865 if (QDF_IS_STATUS_ERROR(status)) { 4866 wma_err("Failed to send apf enable/disable cmd"); 4867 return QDF_STATUS_E_FAILURE; 4868 } 4869 4870 if (apf_enable) 4871 wma_debug("Sent APF Enable on vdevid: %d", vdev_id); 4872 else 4873 wma_debug("Sent APF Disable on vdevid: %d", vdev_id); 4874 4875 return status; 4876 } 4877 4878 QDF_STATUS wma_send_apf_write_work_memory_cmd(WMA_HANDLE handle,struct wmi_apf_write_memory_params * write_params)4879 wma_send_apf_write_work_memory_cmd(WMA_HANDLE handle, 4880 struct wmi_apf_write_memory_params 4881 *write_params) 4882 { 4883 QDF_STATUS status = QDF_STATUS_SUCCESS; 4884 tp_wma_handle wma = (tp_wma_handle) handle; 4885 struct wmi_unified *wmi_handle; 4886 4887 if (wma_validate_handle(wma)) 4888 return QDF_STATUS_E_INVAL; 4889 4890 wmi_handle = wma->wmi_handle; 4891 if (wmi_validate_handle(wmi_handle)) 4892 return QDF_STATUS_E_INVAL; 4893 4894 if (!WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap, 4895 WMI_SERVICE_BPF_OFFLOAD)) { 4896 wma_err("APF cababilities feature bit not enabled"); 4897 return QDF_STATUS_E_FAILURE; 4898 } 4899 4900 if (wmi_unified_send_apf_write_work_memory_cmd(wmi_handle, 4901 write_params)) { 4902 wma_err("Failed to send APF write mem command"); 4903 return QDF_STATUS_E_FAILURE; 4904 } 4905 4906 wma_debug("Sent APF write mem on vdevid: %d", write_params->vdev_id); 4907 return status; 4908 } 4909 wma_apf_read_work_memory_event_handler(void * handle,uint8_t * evt_buf,uint32_t len)4910 int wma_apf_read_work_memory_event_handler(void *handle, uint8_t *evt_buf, 4911 uint32_t len) 4912 { 4913 tp_wma_handle wma_handle; 4914 wmi_unified_t wmi_handle; 4915 struct wmi_apf_read_memory_resp_event_params evt_params = {0}; 4916 QDF_STATUS status; 4917 struct mac_context *pmac = cds_get_context(QDF_MODULE_ID_PE); 4918 4919 wma_debug("handle:%pK event:%pK len:%u", handle, evt_buf, len); 4920 4921 wma_handle = handle; 4922 if (wma_validate_handle(wma_handle)) 4923 return -EINVAL; 4924 4925 wmi_handle = wma_handle->wmi_handle; 4926 if (wmi_validate_handle(wmi_handle)) 4927 return -EINVAL; 4928 4929 if (!pmac) 4930 return -EINVAL; 4931 4932 if (!pmac->sme.apf_read_mem_cb) { 4933 wma_err("Callback not registered"); 4934 return -EINVAL; 4935 } 4936 4937 status = wmi_extract_apf_read_memory_resp_event(wmi_handle, 4938 evt_buf, &evt_params); 4939 if (QDF_IS_STATUS_ERROR(status)) { 4940 wma_err("Event extract failure: %d", status); 4941 return -EINVAL; 4942 } 4943 4944 pmac->sme.apf_read_mem_cb(pmac->hdd_handle, &evt_params); 4945 4946 return 0; 4947 } 4948 wma_send_apf_read_work_memory_cmd(WMA_HANDLE handle,struct wmi_apf_read_memory_params * read_params)4949 QDF_STATUS wma_send_apf_read_work_memory_cmd(WMA_HANDLE handle, 4950 struct wmi_apf_read_memory_params 4951 *read_params) 4952 { 4953 QDF_STATUS status = QDF_STATUS_SUCCESS; 4954 tp_wma_handle wma = (tp_wma_handle) handle; 4955 struct wmi_unified *wmi_handle; 4956 4957 if (wma_validate_handle(wma)) 4958 return QDF_STATUS_E_INVAL; 4959 4960 wmi_handle = wma->wmi_handle; 4961 if (wmi_validate_handle(wmi_handle)) 4962 return QDF_STATUS_E_INVAL; 4963 4964 if (!WMI_SERVICE_IS_ENABLED(wma->wmi_service_bitmap, 4965 WMI_SERVICE_BPF_OFFLOAD)) { 4966 wma_err("APF cababilities feature bit not enabled"); 4967 return QDF_STATUS_E_FAILURE; 4968 } 4969 4970 if (wmi_unified_send_apf_read_work_memory_cmd(wmi_handle, 4971 read_params)) { 4972 wma_err("Failed to send APF read memory command"); 4973 return QDF_STATUS_E_FAILURE; 4974 } 4975 4976 wma_debug("Sent APF read memory on vdevid: %d", read_params->vdev_id); 4977 return status; 4978 } 4979 #endif /* FEATURE_WLAN_APF */ 4980 wma_set_tx_rx_aggr_size(uint8_t vdev_id,uint32_t tx_size,uint32_t rx_size,wmi_vdev_custom_aggr_type_t aggr_type)4981 QDF_STATUS wma_set_tx_rx_aggr_size(uint8_t vdev_id, 4982 uint32_t tx_size, 4983 uint32_t rx_size, 4984 wmi_vdev_custom_aggr_type_t aggr_type) 4985 { 4986 tp_wma_handle wma_handle; 4987 struct wma_txrx_node *intr; 4988 wmi_vdev_set_custom_aggr_size_cmd_fixed_param *cmd; 4989 int32_t len; 4990 wmi_buf_t buf; 4991 u_int8_t *buf_ptr; 4992 int ret; 4993 4994 wma_handle = cds_get_context(QDF_MODULE_ID_WMA); 4995 4996 if (!wma_handle) 4997 return QDF_STATUS_E_INVAL; 4998 4999 intr = wma_handle->interfaces; 5000 if (!intr) { 5001 wma_err("WMA interface is invalid!"); 5002 return QDF_STATUS_E_INVAL; 5003 } 5004 5005 if (aggr_type == WMI_VDEV_CUSTOM_AGGR_TYPE_AMPDU) { 5006 intr[vdev_id].config.tx_ampdu = tx_size; 5007 intr[vdev_id].config.rx_ampdu = rx_size; 5008 } else { 5009 intr[vdev_id].config.tx_amsdu = tx_size; 5010 intr[vdev_id].config.rx_amsdu = rx_size; 5011 } 5012 5013 len = sizeof(*cmd); 5014 buf = wmi_buf_alloc(wma_handle->wmi_handle, len); 5015 if (!buf) 5016 return QDF_STATUS_E_NOMEM; 5017 5018 buf_ptr = (u_int8_t *) wmi_buf_data(buf); 5019 cmd = (wmi_vdev_set_custom_aggr_size_cmd_fixed_param *) buf_ptr; 5020 qdf_mem_zero(cmd, sizeof(*cmd)); 5021 5022 WMITLV_SET_HDR(&cmd->tlv_header, 5023 WMITLV_TAG_STRUC_wmi_vdev_set_custom_aggr_size_cmd_fixed_param, 5024 WMITLV_GET_STRUCT_TLVLEN( 5025 wmi_vdev_set_custom_aggr_size_cmd_fixed_param)); 5026 5027 if (wmi_service_enabled(wma_handle->wmi_handle, 5028 wmi_service_ampdu_tx_buf_size_256_support)) { 5029 cmd->enable_bitmap |= (0x1 << 6); 5030 } 5031 5032 if ((tx_size > ADDBA_TXAGGR_SIZE_HELIUM) && 5033 (tx_size != ADDBA_TXAGGR_SIZE_LITHIUM) && 5034 (tx_size != ADDBA_TXAGGR_SIZE_512) && 5035 (tx_size != ADDBA_TXAGGR_SIZE_BERYLLIUM)) { 5036 wma_err("Invalid AMPDU Size"); 5037 return QDF_STATUS_E_INVAL; 5038 } 5039 5040 cmd->vdev_id = vdev_id; 5041 cmd->tx_aggr_size = tx_size; 5042 cmd->rx_aggr_size = rx_size; 5043 /* bit 2 (aggr_type): TX Aggregation Type (0=A-MPDU, 1=A-MSDU) */ 5044 if (aggr_type == WMI_VDEV_CUSTOM_AGGR_TYPE_AMSDU) 5045 cmd->enable_bitmap |= 0x04; 5046 5047 wma_debug("tx aggr: %d rx aggr: %d vdev: %d enable_bitmap %d", 5048 cmd->tx_aggr_size, cmd->rx_aggr_size, cmd->vdev_id, 5049 cmd->enable_bitmap); 5050 5051 ret = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len, 5052 WMI_VDEV_SET_CUSTOM_AGGR_SIZE_CMDID); 5053 if (ret) { 5054 wmi_buf_free(buf); 5055 return QDF_STATUS_E_FAILURE; 5056 } 5057 5058 return QDF_STATUS_SUCCESS; 5059 } 5060 wma_set_tx_rx_aggr_size_per_ac(WMA_HANDLE handle,uint8_t vdev_id,struct wlan_mlme_qos * qos_aggr,wmi_vdev_custom_aggr_type_t aggr_type)5061 QDF_STATUS wma_set_tx_rx_aggr_size_per_ac(WMA_HANDLE handle, 5062 uint8_t vdev_id, 5063 struct wlan_mlme_qos *qos_aggr, 5064 wmi_vdev_custom_aggr_type_t aggr_type) 5065 { 5066 wmi_vdev_set_custom_aggr_size_cmd_fixed_param *cmd; 5067 int32_t len; 5068 wmi_buf_t buf; 5069 u_int8_t *buf_ptr; 5070 int ret; 5071 int queue_num; 5072 uint32_t tx_aggr_size[4]; 5073 tp_wma_handle wma_handle = (tp_wma_handle)handle; 5074 5075 if (wma_validate_handle(wma_handle)) 5076 return QDF_STATUS_E_INVAL; 5077 5078 tx_aggr_size[0] = qos_aggr->tx_aggregation_size_be; 5079 tx_aggr_size[1] = qos_aggr->tx_aggregation_size_bk; 5080 tx_aggr_size[2] = qos_aggr->tx_aggregation_size_vi; 5081 tx_aggr_size[3] = qos_aggr->tx_aggregation_size_vo; 5082 5083 for (queue_num = 0; queue_num < 4; queue_num++) { 5084 if (tx_aggr_size[queue_num] == 0) 5085 continue; 5086 5087 len = sizeof(*cmd); 5088 buf = wmi_buf_alloc(wma_handle->wmi_handle, len); 5089 if (!buf) 5090 return QDF_STATUS_E_NOMEM; 5091 5092 buf_ptr = (u_int8_t *)wmi_buf_data(buf); 5093 cmd = (wmi_vdev_set_custom_aggr_size_cmd_fixed_param *)buf_ptr; 5094 qdf_mem_zero(cmd, sizeof(*cmd)); 5095 5096 WMITLV_SET_HDR(&cmd->tlv_header, 5097 WMITLV_TAG_STRUC_wmi_vdev_set_custom_aggr_size_cmd_fixed_param, 5098 WMITLV_GET_STRUCT_TLVLEN( 5099 wmi_vdev_set_custom_aggr_size_cmd_fixed_param)); 5100 5101 cmd->vdev_id = vdev_id; 5102 cmd->rx_aggr_size = qos_aggr->rx_aggregation_size; 5103 cmd->tx_aggr_size = tx_aggr_size[queue_num]; 5104 5105 if (wmi_service_enabled(wma_handle->wmi_handle, 5106 wmi_service_ampdu_tx_buf_size_256_support)) { 5107 cmd->enable_bitmap |= (0x1 << 6); 5108 } 5109 5110 if ((tx_aggr_size[queue_num] != ADDBA_TXAGGR_SIZE_LITHIUM) && 5111 (tx_aggr_size[queue_num] > ADDBA_TXAGGR_SIZE_HELIUM)) { 5112 wma_err("Invalid AMPDU Size"); 5113 return QDF_STATUS_E_INVAL; 5114 } 5115 5116 /* bit 5: tx_ac_enable, if set, ac bitmap is valid. */ 5117 cmd->enable_bitmap |= 0x20 | queue_num; 5118 /* bit 2 (aggr_type): TX Aggregation Type (0=A-MPDU, 1=A-MSDU) */ 5119 if (aggr_type == WMI_VDEV_CUSTOM_AGGR_TYPE_AMSDU) 5120 cmd->enable_bitmap |= 0x04; 5121 5122 wma_debug("queue_num: %d, tx aggr: %d rx aggr: %d vdev: %d, bitmap: %d", 5123 queue_num, cmd->tx_aggr_size, 5124 cmd->rx_aggr_size, cmd->vdev_id, 5125 cmd->enable_bitmap); 5126 5127 ret = wmi_unified_cmd_send(wma_handle->wmi_handle, buf, len, 5128 WMI_VDEV_SET_CUSTOM_AGGR_SIZE_CMDID); 5129 if (ret) { 5130 wmi_buf_free(buf); 5131 return QDF_STATUS_E_FAILURE; 5132 } 5133 } 5134 5135 return QDF_STATUS_SUCCESS; 5136 } 5137 wma_set_sw_retry_by_qos(tp_wma_handle handle,uint8_t vdev_id,wmi_vdev_custom_sw_retry_type_t retry_type,wmi_traffic_ac ac_type,uint32_t sw_retry)5138 static QDF_STATUS wma_set_sw_retry_by_qos( 5139 tp_wma_handle handle, uint8_t vdev_id, 5140 wmi_vdev_custom_sw_retry_type_t retry_type, 5141 wmi_traffic_ac ac_type, 5142 uint32_t sw_retry) 5143 { 5144 wmi_vdev_set_custom_sw_retry_th_cmd_fixed_param *cmd; 5145 int32_t len; 5146 wmi_buf_t buf; 5147 u_int8_t *buf_ptr; 5148 int ret; 5149 5150 len = sizeof(*cmd); 5151 buf = wmi_buf_alloc(handle->wmi_handle, len); 5152 5153 if (!buf) 5154 return QDF_STATUS_E_NOMEM; 5155 5156 buf_ptr = (u_int8_t *)wmi_buf_data(buf); 5157 cmd = (wmi_vdev_set_custom_sw_retry_th_cmd_fixed_param *)buf_ptr; 5158 5159 WMITLV_SET_HDR(&cmd->tlv_header, 5160 WMITLV_TAG_STRUC_wmi_vdev_set_custom_sw_retry_th_cmd_fixed_param, 5161 WMITLV_GET_STRUCT_TLVLEN( 5162 wmi_vdev_set_custom_sw_retry_th_cmd_fixed_param)); 5163 5164 cmd->vdev_id = vdev_id; 5165 cmd->ac_type = ac_type; 5166 cmd->sw_retry_type = retry_type; 5167 cmd->sw_retry_th = sw_retry; 5168 5169 wma_debug("ac_type: %d re_type: %d threshold: %d vid: %d", 5170 cmd->ac_type, cmd->sw_retry_type, 5171 cmd->sw_retry_th, cmd->vdev_id); 5172 5173 ret = wmi_unified_cmd_send(handle->wmi_handle, 5174 buf, len, 5175 WMI_VDEV_SET_CUSTOM_SW_RETRY_TH_CMDID); 5176 5177 if (ret) { 5178 wmi_buf_free(buf); 5179 return QDF_STATUS_E_FAILURE; 5180 } 5181 5182 return QDF_STATUS_SUCCESS; 5183 } 5184 wma_set_vdev_sw_retry_th(uint8_t vdev_id,uint8_t sw_retry_count,wmi_vdev_custom_sw_retry_type_t retry_type)5185 QDF_STATUS wma_set_vdev_sw_retry_th(uint8_t vdev_id, uint8_t sw_retry_count, 5186 wmi_vdev_custom_sw_retry_type_t retry_type) 5187 { 5188 QDF_STATUS status = QDF_STATUS_SUCCESS; 5189 tp_wma_handle wma_handle; 5190 uint32_t queue_num; 5191 5192 wma_handle = cds_get_context(QDF_MODULE_ID_WMA); 5193 if (!wma_handle) 5194 return QDF_STATUS_E_FAILURE; 5195 5196 5197 for (queue_num = 0; queue_num < WMI_AC_MAX; queue_num++) { 5198 if (sw_retry_count == 0) 5199 continue; 5200 5201 status = wma_set_sw_retry_by_qos(wma_handle, 5202 vdev_id, 5203 retry_type, 5204 queue_num, 5205 sw_retry_count); 5206 5207 if (QDF_IS_STATUS_ERROR(status)) 5208 return status; 5209 } 5210 5211 return QDF_STATUS_SUCCESS; 5212 } 5213 wma_set_sw_retry_threshold_per_ac(WMA_HANDLE handle,uint8_t vdev_id,struct wlan_mlme_qos * qos_aggr)5214 QDF_STATUS wma_set_sw_retry_threshold_per_ac(WMA_HANDLE handle, 5215 uint8_t vdev_id, 5216 struct wlan_mlme_qos *qos_aggr) 5217 { 5218 QDF_STATUS ret; 5219 int retry_type, queue_num; 5220 uint32_t tx_sw_retry[WMI_VDEV_CUSTOM_SW_RETRY_TYPE_MAX][WMI_AC_MAX]; 5221 uint32_t sw_retry; 5222 tp_wma_handle wma_handle = (tp_wma_handle)handle; 5223 5224 if (wma_validate_handle(wma_handle)) 5225 return QDF_STATUS_E_INVAL; 5226 5227 tx_sw_retry[WMI_VDEV_CUSTOM_SW_RETRY_TYPE_AGGR][WMI_AC_BE] = 5228 qos_aggr->tx_aggr_sw_retry_threshold_be; 5229 tx_sw_retry[WMI_VDEV_CUSTOM_SW_RETRY_TYPE_AGGR][WMI_AC_BK] = 5230 qos_aggr->tx_aggr_sw_retry_threshold_bk; 5231 tx_sw_retry[WMI_VDEV_CUSTOM_SW_RETRY_TYPE_AGGR][WMI_AC_VI] = 5232 qos_aggr->tx_aggr_sw_retry_threshold_vi; 5233 tx_sw_retry[WMI_VDEV_CUSTOM_SW_RETRY_TYPE_AGGR][WMI_AC_VO] = 5234 qos_aggr->tx_aggr_sw_retry_threshold_vo; 5235 5236 tx_sw_retry[WMI_VDEV_CUSTOM_SW_RETRY_TYPE_NONAGGR][WMI_AC_BE] = 5237 qos_aggr->tx_non_aggr_sw_retry_threshold_be; 5238 tx_sw_retry[WMI_VDEV_CUSTOM_SW_RETRY_TYPE_NONAGGR][WMI_AC_BK] = 5239 qos_aggr->tx_non_aggr_sw_retry_threshold_bk; 5240 tx_sw_retry[WMI_VDEV_CUSTOM_SW_RETRY_TYPE_NONAGGR][WMI_AC_VI] = 5241 qos_aggr->tx_non_aggr_sw_retry_threshold_vi; 5242 tx_sw_retry[WMI_VDEV_CUSTOM_SW_RETRY_TYPE_NONAGGR][WMI_AC_VO] = 5243 qos_aggr->tx_non_aggr_sw_retry_threshold_vo; 5244 5245 retry_type = WMI_VDEV_CUSTOM_SW_RETRY_TYPE_NONAGGR; 5246 while (retry_type < WMI_VDEV_CUSTOM_SW_RETRY_TYPE_MAX) { 5247 for (queue_num = 0; queue_num < WMI_AC_MAX; queue_num++) { 5248 if (tx_sw_retry[retry_type][queue_num] == 0) 5249 continue; 5250 5251 sw_retry = tx_sw_retry[retry_type][queue_num]; 5252 ret = wma_set_sw_retry_by_qos(wma_handle, 5253 vdev_id, 5254 retry_type, 5255 queue_num, 5256 sw_retry); 5257 5258 if (QDF_IS_STATUS_ERROR(ret)) 5259 return ret; 5260 } 5261 retry_type++; 5262 } 5263 5264 return QDF_STATUS_SUCCESS; 5265 } 5266 5267 #define MAX_PDEV_SW_RETRY_PARAMS 2 5268 /* params being sent: 5269 * 1.wmi_pdev_param_agg_sw_retry_th 5270 * 2.wmi_pdev_param_non_agg_sw_retry_th 5271 */ 5272 wma_set_sw_retry_threshold(struct wlan_mlme_qos * qos_aggr)5273 QDF_STATUS wma_set_sw_retry_threshold(struct wlan_mlme_qos *qos_aggr) 5274 { 5275 uint32_t max, min, retry; 5276 struct dev_set_param setparam[MAX_PDEV_SW_RETRY_PARAMS]; 5277 QDF_STATUS ret; 5278 uint8_t index = 0; 5279 5280 retry = qos_aggr->tx_aggr_sw_retry_threshold; 5281 max = cfg_max(CFG_TX_AGGR_SW_RETRY); 5282 min = cfg_min(CFG_TX_AGGR_SW_RETRY); 5283 retry = (retry > max) ? max : retry; 5284 retry = (retry < min) ? min : retry; 5285 5286 ret = mlme_check_index_setparam(setparam, 5287 wmi_pdev_param_agg_sw_retry_th, 5288 retry, index++, 5289 MAX_PDEV_SW_RETRY_PARAMS); 5290 if (QDF_IS_STATUS_ERROR(ret)) { 5291 wma_debug("failed to set wmi_pdev_param_agg_sw_retry_th"); 5292 return ret; 5293 } 5294 retry = qos_aggr->tx_non_aggr_sw_retry_threshold; 5295 max = cfg_max(CFG_TX_NON_AGGR_SW_RETRY); 5296 min = cfg_min(CFG_TX_NON_AGGR_SW_RETRY); 5297 retry = (retry > max) ? max : retry; 5298 retry = (retry < min) ? min : retry; 5299 ret = mlme_check_index_setparam(setparam, 5300 wmi_pdev_param_non_agg_sw_retry_th, 5301 retry, index++, 5302 MAX_PDEV_SW_RETRY_PARAMS); 5303 if (QDF_IS_STATUS_ERROR(ret)) { 5304 wma_debug("failed to set wmi_pdev_param_non_agg_sw_retry_th"); 5305 return ret; 5306 } 5307 ret = wma_send_multi_pdev_vdev_set_params(MLME_PDEV_SETPARAM, 5308 WMI_PDEV_ID_SOC, setparam, 5309 index); 5310 return ret; 5311 } 5312 5313 /** 5314 * wma_process_fw_test_cmd() - send unit test command to fw. 5315 * @handle: wma handle 5316 * @wma_fwtest: fw test command 5317 * 5318 * This function send fw test command to fw. 5319 * 5320 * Return: none 5321 */ wma_process_fw_test_cmd(WMA_HANDLE handle,struct set_fwtest_params * wma_fwtest)5322 QDF_STATUS wma_process_fw_test_cmd(WMA_HANDLE handle, 5323 struct set_fwtest_params *wma_fwtest) 5324 { 5325 tp_wma_handle wma_handle = (tp_wma_handle) handle; 5326 struct wmi_unified *wmi_handle; 5327 5328 if (wma_validate_handle(wma_handle)) 5329 return QDF_STATUS_E_INVAL; 5330 5331 wmi_handle = wma_handle->wmi_handle; 5332 if (wmi_validate_handle(wmi_handle)) 5333 return QDF_STATUS_E_INVAL; 5334 5335 if (wmi_unified_fw_test_cmd(wmi_handle, 5336 (struct set_fwtest_params *)wma_fwtest)) { 5337 wma_err("Failed to issue fw test cmd"); 5338 return QDF_STATUS_E_FAILURE; 5339 } 5340 return QDF_STATUS_SUCCESS; 5341 } 5342 5343 /** 5344 * wma_enable_disable_caevent_ind() - Issue WMI command to enable or 5345 * disable ca event indication 5346 * @wma: wma handler 5347 * @val: boolean value true or false 5348 * 5349 * Return: QDF_STATUS 5350 */ wma_enable_disable_caevent_ind(tp_wma_handle wma,uint8_t val)5351 QDF_STATUS wma_enable_disable_caevent_ind(tp_wma_handle wma, uint8_t val) 5352 { 5353 WMI_CHAN_AVOID_RPT_ALLOW_CMD_fixed_param *cmd; 5354 wmi_buf_t wmi_buf; 5355 uint8_t *buf_ptr; 5356 uint32_t len; 5357 struct wmi_unified *wmi_handle; 5358 5359 if (wma_validate_handle(wma)) 5360 return QDF_STATUS_E_INVAL; 5361 5362 wmi_handle = wma->wmi_handle; 5363 if (wmi_validate_handle(wmi_handle)) 5364 return QDF_STATUS_E_INVAL; 5365 5366 len = sizeof(*cmd); 5367 wmi_buf = wmi_buf_alloc(wmi_handle, len); 5368 if (!wmi_buf) 5369 return QDF_STATUS_E_NOMEM; 5370 5371 buf_ptr = (uint8_t *) wmi_buf_data(wmi_buf); 5372 cmd = (WMI_CHAN_AVOID_RPT_ALLOW_CMD_fixed_param *) buf_ptr; 5373 WMITLV_SET_HDR(&cmd->tlv_header, 5374 WMITLV_TAG_STRUC_WMI_CHAN_AVOID_RPT_ALLOW_CMD_fixed_param, 5375 WMITLV_GET_STRUCT_TLVLEN( 5376 WMI_CHAN_AVOID_RPT_ALLOW_CMD_fixed_param)); 5377 cmd->rpt_allow = val; 5378 if (wmi_unified_cmd_send(wmi_handle, wmi_buf, len, 5379 WMI_CHAN_AVOID_RPT_ALLOW_CMDID)) { 5380 wmi_buf_free(wmi_buf); 5381 return QDF_STATUS_E_FAILURE; 5382 } 5383 5384 return QDF_STATUS_SUCCESS; 5385 } 5386 5387 static wma_sar_cb sar_callback; 5388 static void *sar_context; 5389 wma_sar_event_handler(void * handle,uint8_t * evt_buf,uint32_t len)5390 static int wma_sar_event_handler(void *handle, uint8_t *evt_buf, uint32_t len) 5391 { 5392 tp_wma_handle wma_handle; 5393 wmi_unified_t wmi_handle; 5394 struct sar_limit_event *event; 5395 wma_sar_cb callback; 5396 QDF_STATUS status; 5397 5398 wma_info("handle:%pK event:%pK len:%u", handle, evt_buf, len); 5399 5400 wma_handle = handle; 5401 if (wma_validate_handle(wma_handle)) 5402 return QDF_STATUS_E_INVAL; 5403 5404 wmi_handle = wma_handle->wmi_handle; 5405 if (wmi_validate_handle(wmi_handle)) 5406 return QDF_STATUS_E_INVAL; 5407 5408 event = qdf_mem_malloc(sizeof(*event)); 5409 if (!event) 5410 return QDF_STATUS_E_NOMEM; 5411 5412 status = wmi_unified_extract_sar_limit_event(wmi_handle, 5413 evt_buf, event); 5414 if (QDF_IS_STATUS_ERROR(status)) { 5415 wma_err("Event extract failure: %d", status); 5416 qdf_mem_free(event); 5417 return QDF_STATUS_E_INVAL; 5418 } 5419 5420 callback = sar_callback; 5421 sar_callback = NULL; 5422 if (callback) 5423 callback(sar_context, event); 5424 5425 qdf_mem_free(event); 5426 5427 return 0; 5428 } 5429 wma_sar_register_event_handlers(WMA_HANDLE handle)5430 QDF_STATUS wma_sar_register_event_handlers(WMA_HANDLE handle) 5431 { 5432 tp_wma_handle wma_handle = handle; 5433 wmi_unified_t wmi_handle; 5434 5435 if (wma_validate_handle(wma_handle)) 5436 return QDF_STATUS_E_INVAL; 5437 5438 wmi_handle = wma_handle->wmi_handle; 5439 if (wmi_validate_handle(wmi_handle)) 5440 return QDF_STATUS_E_INVAL; 5441 5442 return wmi_unified_register_event_handler(wmi_handle, 5443 wmi_sar_get_limits_event_id, 5444 wma_sar_event_handler, 5445 WMA_RX_WORK_CTX); 5446 } 5447 wma_get_sar_limit(WMA_HANDLE handle,wma_sar_cb callback,void * context)5448 QDF_STATUS wma_get_sar_limit(WMA_HANDLE handle, 5449 wma_sar_cb callback, void *context) 5450 { 5451 tp_wma_handle wma_handle = handle; 5452 wmi_unified_t wmi_handle; 5453 QDF_STATUS status; 5454 5455 if (wma_validate_handle(wma_handle)) 5456 return QDF_STATUS_E_INVAL; 5457 5458 wmi_handle = wma_handle->wmi_handle; 5459 if (wmi_validate_handle(wmi_handle)) 5460 return QDF_STATUS_E_INVAL; 5461 5462 sar_callback = callback; 5463 sar_context = context; 5464 status = wmi_unified_get_sar_limit_cmd(wmi_handle); 5465 if (QDF_IS_STATUS_ERROR(status)) { 5466 wma_err("wmi_unified_get_sar_limit_cmd() error: %u", 5467 status); 5468 sar_callback = NULL; 5469 } 5470 5471 return status; 5472 } 5473 wma_set_sar_limit(WMA_HANDLE handle,struct sar_limit_cmd_params * sar_limit_params)5474 QDF_STATUS wma_set_sar_limit(WMA_HANDLE handle, 5475 struct sar_limit_cmd_params *sar_limit_params) 5476 { 5477 int ret; 5478 tp_wma_handle wma = (tp_wma_handle) handle; 5479 struct wmi_unified *wmi_handle; 5480 5481 if (wma_validate_handle(wma)) 5482 return QDF_STATUS_E_INVAL; 5483 5484 wmi_handle = wma->wmi_handle; 5485 if (wmi_validate_handle(wmi_handle)) 5486 return QDF_STATUS_E_INVAL; 5487 5488 if (!sar_limit_params) { 5489 wma_err("set sar limit ptr NULL"); 5490 return QDF_STATUS_E_INVAL; 5491 } 5492 5493 ret = wmi_unified_send_sar_limit_cmd(wmi_handle, 5494 sar_limit_params); 5495 5496 return ret; 5497 } 5498 wma_send_coex_config_cmd(WMA_HANDLE wma_handle,struct coex_config_params * coex_cfg_params)5499 QDF_STATUS wma_send_coex_config_cmd(WMA_HANDLE wma_handle, 5500 struct coex_config_params *coex_cfg_params) 5501 { 5502 tp_wma_handle wma = (tp_wma_handle)wma_handle; 5503 struct wmi_unified *wmi_handle; 5504 5505 if (wma_validate_handle(wma)) 5506 return QDF_STATUS_E_INVAL; 5507 5508 wmi_handle = wma->wmi_handle; 5509 if (wmi_validate_handle(wmi_handle)) 5510 return QDF_STATUS_E_INVAL; 5511 5512 if (!coex_cfg_params) { 5513 wma_err("coex cfg params ptr NULL"); 5514 return QDF_STATUS_E_INVAL; 5515 } 5516 5517 return wmi_unified_send_coex_config_cmd(wmi_handle, 5518 coex_cfg_params); 5519 } 5520 5521 /** 5522 * wma_get_arp_stats_handler() - handle arp stats data 5523 * indicated by FW 5524 * @handle: wma context 5525 * @data: event buffer 5526 * @data len: length of event buffer 5527 * 5528 * Return: 0 on success 5529 */ wma_get_arp_stats_handler(void * handle,uint8_t * data,uint32_t data_len)5530 int wma_get_arp_stats_handler(void *handle, uint8_t *data, 5531 uint32_t data_len) 5532 { 5533 WMI_VDEV_GET_ARP_STAT_EVENTID_param_tlvs *param_buf; 5534 wmi_vdev_get_arp_stats_event_fixed_param *data_event; 5535 wmi_vdev_get_connectivity_check_stats *connect_stats_event; 5536 uint8_t *buf_ptr; 5537 struct rsp_stats rsp = {0}; 5538 struct mac_context *mac = cds_get_context(QDF_MODULE_ID_PE); 5539 5540 if (!mac) 5541 return -EINVAL; 5542 5543 if (!mac->sme.get_arp_stats_cb) { 5544 wma_err("Callback not registered"); 5545 return -EINVAL; 5546 } 5547 5548 if (!data) { 5549 wma_err("invalid pointer"); 5550 return -EINVAL; 5551 } 5552 param_buf = (WMI_VDEV_GET_ARP_STAT_EVENTID_param_tlvs *)data; 5553 if (!param_buf) { 5554 wma_err("Invalid get arp stats event"); 5555 return -EINVAL; 5556 } 5557 data_event = param_buf->fixed_param; 5558 if (!data_event) { 5559 wma_err("Invalid get arp stats data event"); 5560 return -EINVAL; 5561 } 5562 rsp.arp_req_enqueue = data_event->arp_req_enqueue; 5563 rsp.vdev_id = data_event->vdev_id; 5564 rsp.arp_req_tx_success = data_event->arp_req_tx_success; 5565 rsp.arp_req_tx_failure = data_event->arp_req_tx_failure; 5566 rsp.arp_rsp_recvd = data_event->arp_rsp_recvd; 5567 rsp.out_of_order_arp_rsp_drop_cnt = 5568 data_event->out_of_order_arp_rsp_drop_cnt; 5569 rsp.dad_detected = data_event->dad_detected; 5570 rsp.connect_status = data_event->connect_status; 5571 rsp.ba_session_establishment_status = 5572 data_event->ba_session_establishment_status; 5573 5574 buf_ptr = (uint8_t *)data_event; 5575 buf_ptr = buf_ptr + sizeof(wmi_vdev_get_arp_stats_event_fixed_param) + 5576 WMI_TLV_HDR_SIZE; 5577 connect_stats_event = (wmi_vdev_get_connectivity_check_stats *)buf_ptr; 5578 5579 if (((connect_stats_event->tlv_header & 0xFFFF0000) >> 16 == 5580 WMITLV_TAG_STRUC_wmi_vdev_get_connectivity_check_stats)) { 5581 rsp.connect_stats_present = true; 5582 rsp.tcp_ack_recvd = connect_stats_event->tcp_ack_recvd; 5583 rsp.icmpv4_rsp_recvd = connect_stats_event->icmpv4_rsp_recvd; 5584 wma_debug("tcp_ack_recvd %d icmpv4_rsp_recvd %d", 5585 connect_stats_event->tcp_ack_recvd, 5586 connect_stats_event->icmpv4_rsp_recvd); 5587 } 5588 5589 mac->sme.get_arp_stats_cb(mac->hdd_handle, &rsp, 5590 mac->sme.get_arp_stats_context); 5591 5592 return 0; 5593 } 5594 5595 /** 5596 * wma_unified_power_debug_stats_event_handler() - WMA handler function to 5597 * handle Power stats event from firmware 5598 * @handle: Pointer to wma handle 5599 * @cmd_param_info: Pointer to Power stats event TLV 5600 * @len: Length of the cmd_param_info 5601 * 5602 * Return: 0 on success, error number otherwise 5603 */ 5604 #ifdef WLAN_POWER_DEBUG wma_unified_power_debug_stats_event_handler(void * handle,uint8_t * cmd_param_info,uint32_t len)5605 int wma_unified_power_debug_stats_event_handler(void *handle, 5606 uint8_t *cmd_param_info, uint32_t len) 5607 { 5608 WMI_PDEV_CHIP_POWER_STATS_EVENTID_param_tlvs *param_tlvs; 5609 struct power_stats_response *power_stats_results; 5610 wmi_pdev_chip_power_stats_event_fixed_param *param_buf; 5611 uint32_t power_stats_len, stats_registers_len, *debug_registers; 5612 5613 struct mac_context *mac = (struct mac_context *)cds_get_context(QDF_MODULE_ID_PE); 5614 5615 param_tlvs = 5616 (WMI_PDEV_CHIP_POWER_STATS_EVENTID_param_tlvs *) cmd_param_info; 5617 5618 param_buf = (wmi_pdev_chip_power_stats_event_fixed_param *) 5619 param_tlvs->fixed_param; 5620 if (!mac) { 5621 wma_debug("NULL mac ptr"); 5622 return -EINVAL; 5623 } 5624 5625 if (!param_buf) { 5626 wma_debug("NULL power stats event fixed param"); 5627 return -EINVAL; 5628 } 5629 5630 if (param_buf->num_debug_register > ((WMI_SVC_MSG_MAX_SIZE - 5631 sizeof(wmi_pdev_chip_power_stats_event_fixed_param)) / 5632 sizeof(uint32_t)) || 5633 param_buf->num_debug_register > param_tlvs->num_debug_registers) { 5634 wma_err("excess payload: LEN num_debug_register:%u", 5635 param_buf->num_debug_register); 5636 return -EINVAL; 5637 } 5638 debug_registers = param_tlvs->debug_registers; 5639 stats_registers_len = 5640 (sizeof(uint32_t) * param_buf->num_debug_register); 5641 power_stats_len = stats_registers_len + sizeof(*power_stats_results); 5642 power_stats_results = qdf_mem_malloc(power_stats_len); 5643 if (!power_stats_results) 5644 return -ENOMEM; 5645 5646 wma_debug("Cumulative sleep time %d cumulative total on time %d deep sleep enter counter %d last deep sleep enter tstamp ts %d debug registers fmt %d num debug register %d", 5647 param_buf->cumulative_sleep_time_ms, 5648 param_buf->cumulative_total_on_time_ms, 5649 param_buf->deep_sleep_enter_counter, 5650 param_buf->last_deep_sleep_enter_tstamp_ms, 5651 param_buf->debug_register_fmt, 5652 param_buf->num_debug_register); 5653 5654 power_stats_results->cumulative_sleep_time_ms 5655 = param_buf->cumulative_sleep_time_ms; 5656 power_stats_results->cumulative_total_on_time_ms 5657 = param_buf->cumulative_total_on_time_ms; 5658 power_stats_results->deep_sleep_enter_counter 5659 = param_buf->deep_sleep_enter_counter; 5660 power_stats_results->last_deep_sleep_enter_tstamp_ms 5661 = param_buf->last_deep_sleep_enter_tstamp_ms; 5662 power_stats_results->debug_register_fmt 5663 = param_buf->debug_register_fmt; 5664 power_stats_results->num_debug_register 5665 = param_buf->num_debug_register; 5666 5667 power_stats_results->debug_registers 5668 = (uint32_t *)(power_stats_results + 1); 5669 5670 qdf_mem_copy(power_stats_results->debug_registers, 5671 debug_registers, stats_registers_len); 5672 if (mac->sme.sme_power_debug_stats_callback) 5673 mac->sme.sme_power_debug_stats_callback(mac, 5674 power_stats_results); 5675 5676 qdf_mem_free(power_stats_results); 5677 return 0; 5678 } 5679 #endif 5680 5681 #ifdef WLAN_FEATURE_BEACON_RECEPTION_STATS wma_unified_beacon_debug_stats_event_handler(void * handle,uint8_t * cmd_param_info,uint32_t len)5682 int wma_unified_beacon_debug_stats_event_handler(void *handle, 5683 uint8_t *cmd_param_info, 5684 uint32_t len) 5685 { 5686 WMI_VDEV_BCN_RECEPTION_STATS_EVENTID_param_tlvs *param_tlvs; 5687 struct bcn_reception_stats_rsp *bcn_reception_stats; 5688 wmi_vdev_bcn_recv_stats_fixed_param *param_buf; 5689 struct mac_context *mac = 5690 (struct mac_context *)cds_get_context(QDF_MODULE_ID_PE); 5691 5692 param_tlvs = 5693 (WMI_VDEV_BCN_RECEPTION_STATS_EVENTID_param_tlvs *)cmd_param_info; 5694 if (!param_tlvs) { 5695 wma_err("Invalid stats event"); 5696 return -EINVAL; 5697 } 5698 5699 param_buf = (wmi_vdev_bcn_recv_stats_fixed_param *) 5700 param_tlvs->fixed_param; 5701 if (!param_buf || !mac || !mac->sme.beacon_stats_resp_callback) { 5702 wma_debug("NULL mac ptr or HDD callback is null"); 5703 return -EINVAL; 5704 } 5705 5706 if (!param_buf) { 5707 wma_debug("NULL beacon stats event fixed param"); 5708 return -EINVAL; 5709 } 5710 5711 bcn_reception_stats = qdf_mem_malloc(sizeof(*bcn_reception_stats)); 5712 if (!bcn_reception_stats) 5713 return -ENOMEM; 5714 5715 bcn_reception_stats->total_bcn_cnt = param_buf->total_bcn_cnt; 5716 bcn_reception_stats->total_bmiss_cnt = param_buf->total_bmiss_cnt; 5717 bcn_reception_stats->vdev_id = param_buf->vdev_id; 5718 5719 wma_debug("Total beacon count %d total beacon miss count %d vdev_id %d", 5720 param_buf->total_bcn_cnt, 5721 param_buf->total_bmiss_cnt, 5722 param_buf->vdev_id); 5723 5724 qdf_mem_copy(bcn_reception_stats->bmiss_bitmap, 5725 param_buf->bmiss_bitmap, 5726 MAX_BCNMISS_BITMAP * sizeof(uint32_t)); 5727 5728 mac->sme.beacon_stats_resp_callback(bcn_reception_stats, 5729 mac->sme.beacon_stats_context); 5730 qdf_mem_free(bcn_reception_stats); 5731 return 0; 5732 } 5733 #else wma_unified_beacon_debug_stats_event_handler(void * handle,uint8_t * cmd_param_info,uint32_t len)5734 int wma_unified_beacon_debug_stats_event_handler(void *handle, 5735 uint8_t *cmd_param_info, 5736 uint32_t len) 5737 { 5738 return 0; 5739 } 5740 #endif 5741 5742 #if defined(CLD_PM_QOS) && defined(WLAN_FEATURE_LL_MODE) 5743 int wma_vdev_bcn_latency_event_handler(void * handle,uint8_t * event_info,uint32_t len)5744 wma_vdev_bcn_latency_event_handler(void *handle, 5745 uint8_t *event_info, 5746 uint32_t len) 5747 { 5748 WMI_VDEV_BCN_LATENCY_EVENTID_param_tlvs *param_buf = NULL; 5749 wmi_vdev_bcn_latency_fixed_param *bcn_latency = NULL; 5750 struct mac_context *mac = 5751 (struct mac_context *)cds_get_context(QDF_MODULE_ID_PE); 5752 uint32_t latency_level; 5753 5754 param_buf = (WMI_VDEV_BCN_LATENCY_EVENTID_param_tlvs *)event_info; 5755 if (!param_buf) { 5756 wma_err("Invalid bcn latency event"); 5757 return -EINVAL; 5758 } 5759 5760 bcn_latency = param_buf->fixed_param; 5761 if (!bcn_latency) { 5762 wma_debug("beacon latency event fixed param is NULL"); 5763 return -EINVAL; 5764 } 5765 5766 /* Map the latency value to the level which host expects 5767 * 1 - normal, 2 - moderate, 3 - low, 4 - ultralow 5768 */ 5769 latency_level = bcn_latency->latency_level + 1; 5770 if (latency_level < 1 || latency_level > 4) { 5771 wma_debug("invalid beacon latency level value"); 5772 return -EINVAL; 5773 } 5774 5775 /* Call the registered sme callback */ 5776 mac->sme.beacon_latency_event_cb(latency_level); 5777 5778 return 0; 5779 } 5780 #endif 5781 5782 static void wma_update_scan_channel_info_buf(wmi_unified_t wmi_handle,wmi_chan_info_event_fixed_param * event,struct scan_chan_info * buf,wmi_cca_busy_subband_info * cca_info,uint32_t num_tlvs)5783 wma_update_scan_channel_info_buf(wmi_unified_t wmi_handle, 5784 wmi_chan_info_event_fixed_param *event, 5785 struct scan_chan_info *buf, 5786 wmi_cca_busy_subband_info *cca_info, 5787 uint32_t num_tlvs) 5788 { 5789 uint32_t i; 5790 5791 if (cca_info && num_tlvs > 0) { 5792 buf->subband_info.num_chan = 0; 5793 for (i = 0; i < num_tlvs && i < MAX_WIDE_BAND_SCAN_CHAN; i++) { 5794 buf->subband_info.cca_busy_subband_info[i] = 5795 cca_info->rx_clear_count; 5796 wma_debug("cca_info->rx_clear_count:%d", 5797 cca_info->rx_clear_count); 5798 buf->subband_info.num_chan++; 5799 cca_info++; 5800 } 5801 5802 buf->subband_info.is_wide_band_scan = true; 5803 buf->subband_info.vdev_id = event->vdev_id; 5804 } 5805 } 5806 5807 static void wma_update_scan_channel_subband_info(wmi_chan_info_event_fixed_param * event,struct channel_status * channel_status,wmi_cca_busy_subband_info * cca_info,uint32_t num_tlvs)5808 wma_update_scan_channel_subband_info(wmi_chan_info_event_fixed_param *event, 5809 struct channel_status *channel_status, 5810 wmi_cca_busy_subband_info *cca_info, 5811 uint32_t num_tlvs) 5812 { 5813 uint32_t i; 5814 5815 if (cca_info && num_tlvs > 0) { 5816 channel_status->subband_info.num_chan = 0; 5817 for (i = 0; i < num_tlvs && i < MAX_WIDE_BAND_SCAN_CHAN; i++) { 5818 channel_status->subband_info.cca_busy_subband_info[i] = 5819 cca_info->rx_clear_count; 5820 wma_debug("cca_info->rx_clear_count[%d]: %d", i, 5821 cca_info->rx_clear_count); 5822 channel_status->subband_info.num_chan++; 5823 cca_info++; 5824 } 5825 5826 channel_status->subband_info.is_wide_band_scan = true; 5827 channel_status->subband_info.vdev_id = event->vdev_id; 5828 } 5829 } 5830 wma_chan_info_event_handler(void * handle,uint8_t * event_buf,uint32_t len)5831 int wma_chan_info_event_handler(void *handle, uint8_t *event_buf, uint32_t len) 5832 { 5833 tp_wma_handle wma = (tp_wma_handle)handle; 5834 WMI_CHAN_INFO_EVENTID_param_tlvs *param_buf; 5835 wmi_chan_info_event_fixed_param *event; 5836 struct scan_chan_info buf = {0}; 5837 struct mac_context *mac = NULL; 5838 struct channel_status *channel_status; 5839 bool snr_monitor_enabled; 5840 struct scheduler_msg sme_msg = {0}; 5841 wmi_cca_busy_subband_info *cca_info = NULL; 5842 uint32_t num_tlvs = 0; 5843 bool is_cca_busy_info; 5844 QDF_STATUS qdf_status; 5845 5846 if (wma && wma->cds_context) 5847 mac = (struct mac_context *)cds_get_context(QDF_MODULE_ID_PE); 5848 5849 if (!mac) 5850 return -EINVAL; 5851 5852 param_buf = (WMI_CHAN_INFO_EVENTID_param_tlvs *)event_buf; 5853 if (!param_buf) { 5854 wma_err("Invalid chan info event buffer"); 5855 return -EINVAL; 5856 } 5857 5858 event = param_buf->fixed_param; 5859 if (!event) { 5860 wma_err("Invalid fixed param"); 5861 return -EINVAL; 5862 } 5863 5864 /* Ignore the last channel event data whose command flag is set to 1. 5865 * It’s basically an event with empty data only to indicate scan event 5866 * completion. 5867 */ 5868 if (event->cmd_flags == WMI_CHAN_INFO_END_RESP) 5869 return 0; 5870 5871 cca_info = param_buf->cca_busy_subband_info; 5872 num_tlvs = param_buf->num_cca_busy_subband_info; 5873 is_cca_busy_info = wmi_service_enabled(wma->wmi_handle, 5874 wmi_service_cca_busy_info_for_each_20mhz); 5875 5876 snr_monitor_enabled = wlan_scan_is_snr_monitor_enabled(mac->psoc); 5877 if (snr_monitor_enabled && mac->chan_info_cb) { 5878 buf.tx_frame_count = event->tx_frame_cnt; 5879 buf.clock_freq = event->mac_clk_mhz; 5880 buf.cmd_flag = event->cmd_flags; 5881 buf.freq = event->freq; 5882 buf.noise_floor = event->noise_floor; 5883 buf.cycle_count = event->cycle_count; 5884 buf.rx_clear_count = event->rx_clear_count; 5885 /* wide band scan case */ 5886 if (is_cca_busy_info && num_tlvs) 5887 wma_update_scan_channel_info_buf(wma->wmi_handle, 5888 event, &buf, 5889 cca_info, num_tlvs); 5890 mac->chan_info_cb(&buf); 5891 } 5892 5893 channel_status = qdf_mem_malloc(sizeof(*channel_status)); 5894 if (!channel_status) 5895 return -ENOMEM; 5896 5897 channel_status->channel_freq = event->freq; 5898 channel_status->noise_floor = event->noise_floor; 5899 5900 if (is_cca_busy_info && num_tlvs) 5901 wma_update_scan_channel_subband_info(event, channel_status, 5902 cca_info, num_tlvs); 5903 else 5904 channel_status->rx_clear_count = event->rx_clear_count; 5905 5906 channel_status->cycle_count = event->cycle_count; 5907 channel_status->chan_tx_pwr_range = event->chan_tx_pwr_range; 5908 channel_status->chan_tx_pwr_throughput = event->chan_tx_pwr_tp; 5909 channel_status->rx_frame_count = event->rx_frame_count; 5910 channel_status->bss_rx_cycle_count = event->my_bss_rx_cycle_count; 5911 channel_status->rx_11b_mode_data_duration = 5912 event->rx_11b_mode_data_duration; 5913 channel_status->tx_frame_count = event->tx_frame_cnt; 5914 channel_status->mac_clk_mhz = event->mac_clk_mhz; 5915 channel_status->channel_id = cds_freq_to_chan(event->freq); 5916 channel_status->cmd_flags = event->cmd_flags; 5917 5918 wma_debug("freq %d, nf %d, rcc %u, ch_rcc:%u, cc %u, tx_r %d, tx_t %d, chan_id:%d, flags:%d, cap: %d, num_tlvs:%d", 5919 event->freq, event->noise_floor, 5920 event->rx_clear_count, channel_status->rx_clear_count, 5921 event->cycle_count, event->chan_tx_pwr_range, 5922 event->chan_tx_pwr_tp, channel_status->channel_id, 5923 channel_status->cmd_flags, is_cca_busy_info, num_tlvs); 5924 5925 sme_msg.type = eWNI_SME_CHAN_INFO_EVENT; 5926 sme_msg.bodyptr = channel_status; 5927 sme_msg.bodyval = event->vdev_id; 5928 qdf_status = scheduler_post_message(QDF_MODULE_ID_WMA, 5929 QDF_MODULE_ID_SME, 5930 QDF_MODULE_ID_SME, &sme_msg); 5931 if (QDF_IS_STATUS_ERROR(qdf_status)) 5932 qdf_mem_free(channel_status); 5933 5934 return 0; 5935 } 5936 wma_rx_aggr_failure_event_handler(void * handle,u_int8_t * event_buf,u_int32_t len)5937 int wma_rx_aggr_failure_event_handler(void *handle, u_int8_t *event_buf, 5938 u_int32_t len) 5939 { 5940 WMI_REPORT_RX_AGGR_FAILURE_EVENTID_param_tlvs *param_buf; 5941 struct sir_sme_rx_aggr_hole_ind *rx_aggr_hole_event; 5942 wmi_rx_aggr_failure_event_fixed_param *rx_aggr_failure_info; 5943 wmi_rx_aggr_failure_info *hole_info; 5944 uint32_t i, alloc_len; 5945 struct mac_context *mac; 5946 5947 mac = (struct mac_context *)cds_get_context(QDF_MODULE_ID_PE); 5948 if (!mac || !mac->sme.stats_ext2_cb) { 5949 wma_debug("NULL mac ptr or HDD callback is null"); 5950 return -EINVAL; 5951 } 5952 5953 param_buf = (WMI_REPORT_RX_AGGR_FAILURE_EVENTID_param_tlvs *)event_buf; 5954 if (!param_buf) { 5955 wma_err("Invalid stats ext event buf"); 5956 return -EINVAL; 5957 } 5958 5959 rx_aggr_failure_info = param_buf->fixed_param; 5960 hole_info = param_buf->failure_info; 5961 5962 if (rx_aggr_failure_info->num_failure_info > ((WMI_SVC_MSG_MAX_SIZE - 5963 sizeof(*rx_aggr_hole_event)) / 5964 sizeof(rx_aggr_hole_event->hole_info_array[0]))) { 5965 wma_err("Excess data from WMI num_failure_info %d", 5966 rx_aggr_failure_info->num_failure_info); 5967 return -EINVAL; 5968 } 5969 5970 alloc_len = sizeof(*rx_aggr_hole_event) + 5971 (rx_aggr_failure_info->num_failure_info)* 5972 sizeof(rx_aggr_hole_event->hole_info_array[0]); 5973 rx_aggr_hole_event = qdf_mem_malloc(alloc_len); 5974 if (!rx_aggr_hole_event) 5975 return -ENOMEM; 5976 5977 rx_aggr_hole_event->hole_cnt = rx_aggr_failure_info->num_failure_info; 5978 if (rx_aggr_hole_event->hole_cnt > param_buf->num_failure_info) { 5979 wma_err("Invalid no of hole count: %d", 5980 rx_aggr_hole_event->hole_cnt); 5981 qdf_mem_free(rx_aggr_hole_event); 5982 return -EINVAL; 5983 } 5984 wma_debug("aggr holes_sum: %d\n", 5985 rx_aggr_failure_info->num_failure_info); 5986 for (i = 0; i < rx_aggr_hole_event->hole_cnt; i++) { 5987 rx_aggr_hole_event->hole_info_array[i] = 5988 hole_info->end_seq - hole_info->start_seq + 1; 5989 wma_nofl_debug("aggr_index: %d\tstart_seq: %d\tend_seq: %d\t" 5990 "hole_info: %d mpdu lost", 5991 i, hole_info->start_seq, hole_info->end_seq, 5992 rx_aggr_hole_event->hole_info_array[i]); 5993 hole_info++; 5994 } 5995 5996 mac->sme.stats_ext2_cb(mac->hdd_handle, rx_aggr_hole_event); 5997 qdf_mem_free(rx_aggr_hole_event); 5998 5999 return 0; 6000 } 6001 wma_wlan_bt_activity_evt_handler(void * handle,uint8_t * event,uint32_t len)6002 int wma_wlan_bt_activity_evt_handler(void *handle, uint8_t *event, uint32_t len) 6003 { 6004 wmi_coex_bt_activity_event_fixed_param *fixed_param; 6005 WMI_WLAN_COEX_BT_ACTIVITY_EVENTID_param_tlvs *param_buf = 6006 (WMI_WLAN_COEX_BT_ACTIVITY_EVENTID_param_tlvs *)event; 6007 struct scheduler_msg sme_msg = {0}; 6008 QDF_STATUS qdf_status; 6009 6010 if (!param_buf) { 6011 wma_err("Invalid BT activity event buffer"); 6012 return -EINVAL; 6013 } 6014 6015 fixed_param = param_buf->fixed_param; 6016 if (!fixed_param) { 6017 wma_err("Invalid BT activity event fixed param buffer"); 6018 return -EINVAL; 6019 } 6020 6021 wma_info("Received BT activity event %u", 6022 fixed_param->coex_profile_evt); 6023 6024 sme_msg.type = eWNI_SME_BT_ACTIVITY_INFO_IND; 6025 sme_msg.bodyptr = NULL; 6026 sme_msg.bodyval = fixed_param->coex_profile_evt; 6027 6028 qdf_status = scheduler_post_message(QDF_MODULE_ID_WMA, 6029 QDF_MODULE_ID_SME, 6030 QDF_MODULE_ID_SME, &sme_msg); 6031 if (QDF_IS_STATUS_ERROR(qdf_status)) 6032 return -EINVAL; 6033 6034 return 0; 6035 } 6036 wma_pdev_div_info_evt_handler(void * handle,u_int8_t * event_buf,u_int32_t len)6037 int wma_pdev_div_info_evt_handler(void *handle, u_int8_t *event_buf, 6038 u_int32_t len) 6039 { 6040 WMI_PDEV_DIV_RSSI_ANTID_EVENTID_param_tlvs *param_buf; 6041 wmi_pdev_div_rssi_antid_event_fixed_param *event; 6042 struct chain_rssi_result chain_rssi_result; 6043 u_int32_t i; 6044 u_int8_t macaddr[QDF_MAC_ADDR_SIZE]; 6045 tp_wma_handle wma = (tp_wma_handle)handle; 6046 6047 struct mac_context *pmac = (struct mac_context *)cds_get_context( 6048 QDF_MODULE_ID_PE); 6049 if (!pmac || !wma) { 6050 wma_err("Invalid pmac or wma"); 6051 return -EINVAL; 6052 } 6053 6054 if (!pmac->sme.get_chain_rssi_cb) { 6055 wma_err("Invalid get_chain_rssi_cb"); 6056 return -EINVAL; 6057 } 6058 param_buf = (WMI_PDEV_DIV_RSSI_ANTID_EVENTID_param_tlvs *) event_buf; 6059 if (!param_buf) { 6060 wma_err("Invalid rssi antid event buffer"); 6061 return -EINVAL; 6062 } 6063 6064 event = param_buf->fixed_param; 6065 if (!event) { 6066 wma_err("Invalid fixed param"); 6067 return -EINVAL; 6068 } 6069 6070 if (event->num_chains_valid > CHAIN_MAX_NUM) { 6071 wma_err("Invalid num of chains"); 6072 return -EINVAL; 6073 } 6074 6075 qdf_mem_zero(&chain_rssi_result, sizeof(chain_rssi_result)); 6076 6077 WMI_MAC_ADDR_TO_CHAR_ARRAY(&event->macaddr, macaddr); 6078 wma_debug("macaddr: " QDF_MAC_ADDR_FMT, QDF_MAC_ADDR_REF(macaddr)); 6079 6080 wma_debug("num_chains_valid: %d", event->num_chains_valid); 6081 chain_rssi_result.num_chains_valid = event->num_chains_valid; 6082 6083 qdf_mem_copy(chain_rssi_result.chain_rssi, event->chain_rssi, 6084 sizeof(event->chain_rssi)); 6085 6086 qdf_mem_copy(chain_rssi_result.chain_evm, event->chain_evm, 6087 sizeof(event->chain_evm)); 6088 6089 qdf_mem_copy(chain_rssi_result.ant_id, event->ant_id, 6090 sizeof(event->ant_id)); 6091 6092 for (i = 0; i < chain_rssi_result.num_chains_valid; i++) { 6093 wma_nofl_debug("chain_rssi: %d, chain_evm: %d,ant_id: %d", 6094 chain_rssi_result.chain_rssi[i], 6095 chain_rssi_result.chain_evm[i], 6096 chain_rssi_result.ant_id[i]); 6097 6098 if (!wmi_service_enabled(wma->wmi_handle, 6099 wmi_service_hw_db2dbm_support)) { 6100 if (chain_rssi_result.chain_rssi[i] != 6101 WMA_INVALID_PER_CHAIN_SNR) 6102 chain_rssi_result.chain_rssi[i] += 6103 WMA_TGT_NOISE_FLOOR_DBM; 6104 else 6105 chain_rssi_result.chain_rssi[i] = 6106 WMA_INVALID_PER_CHAIN_RSSI; 6107 } 6108 } 6109 6110 pmac->sme.get_chain_rssi_cb(pmac->sme.get_chain_rssi_context, 6111 &chain_rssi_result); 6112 6113 return 0; 6114 } 6115 wma_vdev_obss_detection_info_handler(void * handle,uint8_t * event,uint32_t len)6116 int wma_vdev_obss_detection_info_handler(void *handle, uint8_t *event, 6117 uint32_t len) 6118 { 6119 tp_wma_handle wma = (tp_wma_handle) handle; 6120 struct wmi_obss_detect_info *obss_detection; 6121 QDF_STATUS status; 6122 6123 if (!event) { 6124 wma_err("Invalid obss_detection_info event buffer"); 6125 return -EINVAL; 6126 } 6127 6128 obss_detection = qdf_mem_malloc(sizeof(*obss_detection)); 6129 if (!obss_detection) 6130 return -ENOMEM; 6131 6132 status = wmi_unified_extract_obss_detection_info(wma->wmi_handle, 6133 event, obss_detection); 6134 6135 if (QDF_IS_STATUS_ERROR(status)) { 6136 wma_err("Failed to extract obss info"); 6137 qdf_mem_free(obss_detection); 6138 return -EINVAL; 6139 } 6140 6141 if (!wma_is_vdev_valid(obss_detection->vdev_id)) { 6142 wma_err("Invalid vdev id %d", obss_detection->vdev_id); 6143 qdf_mem_free(obss_detection); 6144 return -EINVAL; 6145 } 6146 6147 wma_send_msg(wma, WMA_OBSS_DETECTION_INFO, obss_detection, 0); 6148 6149 return 0; 6150 } 6151 wma_send_set_key_rsp(uint8_t vdev_id,bool pairwise,uint8_t key_index)6152 static void wma_send_set_key_rsp(uint8_t vdev_id, bool pairwise, 6153 uint8_t key_index) 6154 { 6155 tSetStaKeyParams *key_info_uc; 6156 tSetBssKeyParams *key_info_mc; 6157 struct wlan_crypto_key *crypto_key; 6158 struct wlan_objmgr_vdev *vdev; 6159 tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA); 6160 struct qdf_mac_addr bcast_mac = QDF_MAC_ADDR_BCAST_INIT; 6161 6162 if (!wma) 6163 return; 6164 6165 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(wma->psoc, 6166 vdev_id, 6167 WLAN_LEGACY_WMA_ID); 6168 if (!vdev) { 6169 wma_err("VDEV object not found"); 6170 return; 6171 } 6172 crypto_key = wlan_crypto_get_key(vdev, key_index); 6173 6174 wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_WMA_ID); 6175 if (!crypto_key) { 6176 wma_debug("crypto_key not found"); 6177 return; 6178 } 6179 6180 if (pairwise) { 6181 key_info_uc = qdf_mem_malloc(sizeof(*key_info_uc)); 6182 if (!key_info_uc) 6183 return; 6184 key_info_uc->vdev_id = vdev_id; 6185 key_info_uc->status = QDF_STATUS_SUCCESS; 6186 key_info_uc->key_len = crypto_key->keylen; 6187 qdf_mem_copy(&key_info_uc->macaddr, &crypto_key->macaddr, 6188 QDF_MAC_ADDR_SIZE); 6189 wma_send_msg_high_priority(wma, WMA_SET_STAKEY_RSP, 6190 key_info_uc, 0); 6191 wlan_release_peer_key_wakelock(wma->pdev, crypto_key->macaddr); 6192 } else { 6193 key_info_mc = qdf_mem_malloc(sizeof(*key_info_mc)); 6194 if (!key_info_mc) 6195 return; 6196 key_info_mc->vdev_id = vdev_id; 6197 key_info_mc->status = QDF_STATUS_SUCCESS; 6198 key_info_mc->key_len = crypto_key->keylen; 6199 qdf_mem_copy(&key_info_mc->macaddr, &bcast_mac, 6200 QDF_MAC_ADDR_SIZE); 6201 wma_send_msg_high_priority(wma, WMA_SET_BSSKEY_RSP, 6202 key_info_mc, 0); 6203 } 6204 } 6205 wma_set_peer_ucast_cipher(uint8_t * mac_addr,int32_t uc_cipher,int32_t cipher_cap)6206 void wma_set_peer_ucast_cipher(uint8_t *mac_addr, int32_t uc_cipher, 6207 int32_t cipher_cap) 6208 { 6209 struct wlan_objmgr_peer *peer; 6210 tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA); 6211 6212 if (!wma) 6213 return; 6214 peer = wlan_objmgr_get_peer(wma->psoc, 6215 wlan_objmgr_pdev_get_pdev_id(wma->pdev), 6216 mac_addr, WLAN_LEGACY_WMA_ID); 6217 if (!peer) { 6218 wma_err("Peer of peer_mac "QDF_MAC_ADDR_FMT" not found", 6219 QDF_MAC_ADDR_REF(mac_addr)); 6220 return; 6221 } 6222 6223 wlan_crypto_set_peer_param(peer, WLAN_CRYPTO_PARAM_CIPHER_CAP, 6224 cipher_cap); 6225 wlan_crypto_set_peer_param(peer, WLAN_CRYPTO_PARAM_UCAST_CIPHER, 6226 uc_cipher); 6227 wlan_objmgr_peer_release_ref(peer, WLAN_LEGACY_WMA_ID); 6228 6229 wma_debug("Set unicast cipher %x and cap %x for "QDF_MAC_ADDR_FMT, 6230 uc_cipher, cipher_cap, QDF_MAC_ADDR_REF(mac_addr)); 6231 } 6232 wma_update_set_key(uint8_t session_id,bool pairwise,uint8_t key_index,enum wlan_crypto_cipher_type cipher_type)6233 void wma_update_set_key(uint8_t session_id, bool pairwise, 6234 uint8_t key_index, 6235 enum wlan_crypto_cipher_type cipher_type) 6236 { 6237 tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA); 6238 struct wma_txrx_node *iface; 6239 6240 if (!wma) 6241 return; 6242 6243 iface = &wma->interfaces[session_id]; 6244 if (!iface) { 6245 wma_err("iface not found for session id %d", session_id); 6246 return; 6247 } 6248 6249 if (iface) 6250 iface->is_waiting_for_key = false; 6251 6252 wma_send_set_key_rsp(session_id, pairwise, key_index); 6253 } 6254 wma_vdev_bss_color_collision_info_handler(void * handle,uint8_t * event,uint32_t len)6255 int wma_vdev_bss_color_collision_info_handler(void *handle, 6256 uint8_t *event, 6257 uint32_t len) 6258 { 6259 tp_wma_handle wma = (tp_wma_handle) handle; 6260 struct wmi_obss_color_collision_info *obss_color_info; 6261 QDF_STATUS status; 6262 6263 if (!event) { 6264 wma_err("Invalid obss_color_collision event buffer"); 6265 return -EINVAL; 6266 } 6267 6268 obss_color_info = qdf_mem_malloc(sizeof(*obss_color_info)); 6269 if (!obss_color_info) 6270 return -ENOMEM; 6271 6272 status = wmi_unified_extract_obss_color_collision_info(wma->wmi_handle, 6273 event, 6274 obss_color_info); 6275 6276 if (QDF_IS_STATUS_ERROR(status)) { 6277 wma_err("Failed to extract obss color info"); 6278 qdf_mem_free(obss_color_info); 6279 return -EINVAL; 6280 } 6281 6282 if (!wma_is_vdev_valid(obss_color_info->vdev_id)) { 6283 wma_err("Invalid vdev id %d", obss_color_info->vdev_id); 6284 qdf_mem_free(obss_color_info); 6285 return -EINVAL; 6286 } 6287 6288 wma_send_msg(wma, WMA_OBSS_COLOR_COLLISION_INFO, obss_color_info, 0); 6289 6290 return 0; 6291 } 6292 6293 #ifdef FEATURE_ANI_LEVEL_REQUEST wma_get_ani_level_evt_handler(void * handle,uint8_t * event_buf,uint32_t len)6294 int wma_get_ani_level_evt_handler(void *handle, uint8_t *event_buf, 6295 uint32_t len) 6296 { 6297 tp_wma_handle wma = (tp_wma_handle)handle; 6298 struct wmi_host_ani_level_event *ani = NULL; 6299 uint32_t num_freqs = 0; 6300 QDF_STATUS status; 6301 struct mac_context *pmac; 6302 int ret = 0; 6303 6304 pmac = (struct mac_context *)cds_get_context(QDF_MODULE_ID_PE); 6305 if (!pmac || !wma) { 6306 wma_err("Invalid pmac or wma"); 6307 return -EINVAL; 6308 } 6309 6310 status = wmi_unified_extract_ani_level(wma->wmi_handle, event_buf, 6311 &ani, &num_freqs); 6312 6313 if (QDF_IS_STATUS_ERROR(status)) { 6314 wma_err("Failed to extract ani level"); 6315 return -EINVAL; 6316 } 6317 6318 if (!pmac->ani_params.ani_level_cb) { 6319 wma_err("Invalid ani_level_cb"); 6320 ret = -EINVAL; 6321 goto free; 6322 } 6323 6324 pmac->ani_params.ani_level_cb(ani, num_freqs, 6325 pmac->ani_params.context); 6326 6327 free: 6328 qdf_mem_free(ani); 6329 return ret; 6330 } 6331 #else wma_get_ani_level_evt_handler(void * handle,uint8_t * event_buf,uint32_t len)6332 int wma_get_ani_level_evt_handler(void *handle, uint8_t *event_buf, 6333 uint32_t len) 6334 { 6335 return 0; 6336 } 6337 #endif 6338 6339