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