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