1 /* 2 * Copyright (c) 2013-2021 The Linux Foundation. All rights reserved. 3 * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for 6 * any purpose with or without fee is hereby granted, provided that the 7 * above copyright notice and this permission notice appear in all 8 * copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 11 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 12 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 13 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 16 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 17 * PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 /** 21 * DOC: wma_scan_roam.c 22 * This file contains functions related to scan and 23 * roaming functionality. 24 */ 25 26 /* Header files */ 27 28 #include "wma.h" 29 #include "wma_api.h" 30 #include "cds_api.h" 31 #include "wmi_unified_api.h" 32 #include "wlan_qct_sys.h" 33 #include "wni_api.h" 34 #include "ani_global.h" 35 #include "wmi_unified.h" 36 #include "wni_cfg.h" 37 #include <cdp_txrx_peer_ops.h> 38 #include <cdp_txrx_cfg.h> 39 #include <cdp_txrx_ctrl.h> 40 41 #include "qdf_nbuf.h" 42 #include "qdf_types.h" 43 #include "qdf_mem.h" 44 #include "wlan_dlm_api.h" 45 46 #include "wma_types.h" 47 #include "lim_api.h" 48 #include "lim_session_utils.h" 49 50 #include "cds_utils.h" 51 #include "wlan_policy_mgr_api.h" 52 #include <wlan_utility.h> 53 54 #if !defined(REMOVE_PKT_LOG) 55 #include "pktlog_ac.h" 56 #endif /* REMOVE_PKT_LOG */ 57 58 #include "dbglog_host.h" 59 #include "csr_api.h" 60 #include "ol_fw.h" 61 62 #include "wma_internal.h" 63 #if defined(CONFIG_HL_SUPPORT) 64 #include "wlan_tgt_def_config_hl.h" 65 #else 66 #include "wlan_tgt_def_config.h" 67 #endif 68 #include "wlan_reg_services_api.h" 69 #include "wlan_roam_debug.h" 70 #include "wlan_mlme_public_struct.h" 71 #include "wlan_mgmt_txrx_utils_api.h" 72 73 /* This is temporary, should be removed */ 74 #include "ol_htt_api.h" 75 #include <cdp_txrx_handle.h> 76 #include "wma_he.h" 77 #include <wlan_scan_public_structs.h> 78 #include <wlan_scan_ucfg_api.h> 79 #include "wma_nan_datapath.h" 80 #include "wlan_mlme_api.h" 81 #include <wlan_mlme_main.h> 82 #include <wlan_crypto_global_api.h> 83 #include <cdp_txrx_mon.h> 84 #include <cdp_txrx_ctrl.h> 85 #include "wlan_dlm_api.h" 86 #include "wlan_cm_roam_api.h" 87 #ifdef FEATURE_WLAN_DIAG_SUPPORT /* FEATURE_WLAN_DIAG_SUPPORT */ 88 #include "host_diag_core_log.h" 89 #endif /* FEATURE_WLAN_DIAG_SUPPORT */ 90 #include <../../core/src/wlan_cm_roam_i.h> 91 #include "wlan_cm_roam_api.h" 92 #include "wlan_mlo_mgr_roam.h" 93 #include "lim_mlo.h" 94 #ifdef FEATURE_WLAN_EXTSCAN 95 #define WMA_EXTSCAN_CYCLE_WAKE_LOCK_DURATION WAKELOCK_DURATION_RECOMMENDED 96 97 /* 98 * Maximum number of entries that could be present in the 99 * WMI_EXTSCAN_HOTLIST_MATCH_EVENT buffer from the firmware 100 */ 101 #define WMA_EXTSCAN_MAX_HOTLIST_ENTRIES 10 102 #endif 103 104 static inline wmi_host_channel_width 105 wma_map_phy_ch_bw_to_wmi_channel_width(enum phy_ch_width ch_width) 106 { 107 switch (ch_width) { 108 case CH_WIDTH_20MHZ: 109 return WMI_HOST_CHAN_WIDTH_20; 110 case CH_WIDTH_40MHZ: 111 return WMI_HOST_CHAN_WIDTH_40; 112 case CH_WIDTH_80MHZ: 113 return WMI_HOST_CHAN_WIDTH_80; 114 case CH_WIDTH_160MHZ: 115 return WMI_HOST_CHAN_WIDTH_160; 116 case CH_WIDTH_5MHZ: 117 return WMI_HOST_CHAN_WIDTH_5; 118 case CH_WIDTH_10MHZ: 119 return WMI_HOST_CHAN_WIDTH_10; 120 case CH_WIDTH_320MHZ: 121 return WMI_HOST_CHAN_WIDTH_320; 122 default: 123 return WMI_HOST_CHAN_WIDTH_20; 124 } 125 } 126 127 #define WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ 0 128 #define WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ 1 129 #define WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ 2 130 #define WNI_CFG_VHT_CHANNEL_WIDTH_80_PLUS_80MHZ 3 131 132 #if defined(WLAN_FEATURE_11BE) 133 static void wma_update_ch_list_11be_params(struct ch_params *ch) 134 { 135 ch->ch_width = CH_WIDTH_320MHZ; 136 } 137 #else /* !WLAN_FEATURE_11BE */ 138 static void wma_update_ch_list_11be_params(struct ch_params *ch) 139 { 140 ch->ch_width = CH_WIDTH_160MHZ; 141 } 142 #endif /* WLAN_FEATURE_11BE */ 143 144 /** 145 * wma_update_channel_list() - update channel list 146 * @handle: wma handle 147 * @chan_list: channel list 148 * 149 * Function is used to update the support channel list in fw. 150 * 151 * Return: QDF status 152 */ 153 QDF_STATUS wma_update_channel_list(WMA_HANDLE handle, 154 tSirUpdateChanList *chan_list) 155 { 156 tp_wma_handle wma_handle = (tp_wma_handle) handle; 157 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS; 158 int i, len; 159 struct scan_chan_list_params *scan_ch_param; 160 struct channel_param *chan_p; 161 struct ch_params ch_params = {0}; 162 163 len = sizeof(struct channel_param) * chan_list->numChan + 164 offsetof(struct scan_chan_list_params, ch_param[0]); 165 scan_ch_param = qdf_mem_malloc(len); 166 if (!scan_ch_param) 167 return QDF_STATUS_E_NOMEM; 168 169 qdf_mem_zero(scan_ch_param, len); 170 wma_debug("no of channels = %d", chan_list->numChan); 171 chan_p = &scan_ch_param->ch_param[0]; 172 scan_ch_param->nallchans = chan_list->numChan; 173 scan_ch_param->max_bw_support_present = true; 174 wma_handle->saved_chan.num_channels = chan_list->numChan; 175 wma_debug("ht %d, vht %d, vht_24 %d", chan_list->ht_en, 176 chan_list->vht_en, chan_list->vht_24_en); 177 178 for (i = 0; i < chan_list->numChan; ++i) { 179 chan_p->mhz = chan_list->chanParam[i].freq; 180 chan_p->cfreq1 = chan_p->mhz; 181 chan_p->cfreq2 = 0; 182 wma_handle->saved_chan.ch_freq_list[i] = 183 chan_list->chanParam[i].freq; 184 185 if (chan_list->chanParam[i].dfsSet) { 186 chan_p->is_chan_passive = 1; 187 chan_p->dfs_set = 1; 188 } 189 190 if (chan_list->chanParam[i].nan_disabled) 191 chan_p->nan_disabled = 1; 192 193 if (chan_p->mhz < WMA_2_4_GHZ_MAX_FREQ) { 194 chan_p->phy_mode = MODE_11G; 195 if (chan_list->vht_en && chan_list->vht_24_en) 196 chan_p->allow_vht = 1; 197 } else { 198 chan_p->phy_mode = MODE_11A; 199 if (chan_list->vht_en && 200 !(WLAN_REG_IS_6GHZ_CHAN_FREQ(chan_p->mhz))) 201 chan_p->allow_vht = 1; 202 } 203 204 if (chan_list->ht_en && 205 !(WLAN_REG_IS_6GHZ_CHAN_FREQ(chan_p->mhz))) 206 chan_p->allow_ht = 1; 207 208 if (chan_list->he_en) 209 chan_p->allow_he = 1; 210 211 if (chan_list->eht_en) 212 chan_p->allow_eht = 1; 213 214 if (chan_list->chanParam[i].half_rate) 215 chan_p->half_rate = 1; 216 else if (chan_list->chanParam[i].quarter_rate) 217 chan_p->quarter_rate = 1; 218 219 if (WLAN_REG_IS_6GHZ_CHAN_FREQ(chan_p->mhz) && 220 wlan_reg_is_6ghz_psc_chan_freq(chan_p->mhz)) 221 chan_p->psc_channel = 1; 222 223 /*TODO: Set WMI_SET_CHANNEL_MIN_POWER */ 224 /*TODO: Set WMI_SET_CHANNEL_ANTENNA_MAX */ 225 /*TODO: WMI_SET_CHANNEL_REG_CLASSID */ 226 chan_p->maxregpower = chan_list->chanParam[i].pwr; 227 228 wma_update_ch_list_11be_params(&ch_params); 229 230 wlan_reg_set_channel_params_for_pwrmode(wma_handle->pdev, 231 chan_p->mhz, 0, 232 &ch_params, 233 REG_CURRENT_PWR_MODE); 234 235 chan_p->max_bw_supported = 236 wma_map_phy_ch_bw_to_wmi_channel_width(ch_params.ch_width); 237 chan_p++; 238 } 239 240 qdf_status = wmi_unified_scan_chan_list_cmd_send(wma_handle->wmi_handle, 241 scan_ch_param); 242 243 if (QDF_IS_STATUS_ERROR(qdf_status)) 244 wma_err("Failed to send WMI_SCAN_CHAN_LIST_CMDID"); 245 246 qdf_mem_free(scan_ch_param); 247 248 return qdf_status; 249 } 250 251 /** 252 * wma_handle_disconnect_reason() - Send del sta msg to lim on receiving 253 * @wma_handle: wma handle 254 * @vdev_id: vdev id 255 * @reason: disconnection reason from fw 256 * 257 * Return: None 258 */ 259 static void wma_handle_disconnect_reason(tp_wma_handle wma_handle, 260 uint32_t vdev_id, uint32_t reason) 261 { 262 tpDeleteStaContext del_sta_ctx; 263 264 del_sta_ctx = qdf_mem_malloc(sizeof(tDeleteStaContext)); 265 if (!del_sta_ctx) 266 return; 267 268 del_sta_ctx->vdev_id = vdev_id; 269 del_sta_ctx->reasonCode = reason; 270 wma_send_msg(wma_handle, SIR_LIM_DELETE_STA_CONTEXT_IND, 271 (void *)del_sta_ctx, 0); 272 } 273 274 #ifdef WLAN_FEATURE_ROAM_OFFLOAD 275 QDF_STATUS 276 cm_handle_auth_offload(struct auth_offload_event *auth_event) 277 { 278 QDF_STATUS status; 279 tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA); 280 struct mac_context *mac_ctx; 281 282 mac_ctx = cds_get_context(QDF_MODULE_ID_PE); 283 if (!mac_ctx || !wma) { 284 QDF_ASSERT(0); 285 return QDF_STATUS_E_FAILURE; 286 } 287 288 cds_host_diag_log_work(&wma->roam_preauth_wl, 289 WMA_ROAM_PREAUTH_WAKE_LOCK_DURATION, 290 WIFI_POWER_EVENT_WAKELOCK_WOW); 291 292 qdf_wake_lock_timeout_acquire(&wma->roam_ho_wl, 293 WMA_ROAM_HO_WAKE_LOCK_DURATION); 294 295 lim_sae_auth_cleanup_retry(mac_ctx, auth_event->vdev_id); 296 wlan_cm_set_sae_auth_ta(mac_ctx->pdev, 297 auth_event->vdev_id, 298 auth_event->ta); 299 300 wlan_cm_store_mlo_roam_peer_address(mac_ctx->pdev, auth_event); 301 302 status = 303 wlan_cm_update_offload_ssid_from_candidate(mac_ctx->pdev, 304 auth_event->vdev_id, 305 &auth_event->ap_bssid); 306 307 if (QDF_IS_STATUS_ERROR(status)) { 308 wma_err_rl("Set offload ssid failed %d", status); 309 return QDF_STATUS_E_FAILURE; 310 } 311 312 status = wma->csr_roam_auth_event_handle_cb(mac_ctx, auth_event->vdev_id, 313 auth_event->ap_bssid, 314 auth_event->akm); 315 if (QDF_IS_STATUS_ERROR(status)) { 316 wma_err_rl("Trigger pre-auth failed"); 317 return QDF_STATUS_E_FAILURE; 318 } 319 return QDF_STATUS_SUCCESS; 320 } 321 322 QDF_STATUS 323 cm_handle_disconnect_reason(struct vdev_disconnect_event_data *data) 324 { 325 tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA); 326 327 if (!wma) { 328 QDF_ASSERT(0); 329 return QDF_STATUS_E_FAILURE; 330 } 331 switch (data->reason) { 332 case CM_DISCONNECT_REASON_CSA_SA_QUERY_TIMEOUT: 333 wma_handle_disconnect_reason(wma, data->vdev_id, 334 HAL_DEL_STA_REASON_CODE_SA_QUERY_TIMEOUT); 335 break; 336 case CM_DISCONNECT_REASON_MOVE_TO_CELLULAR: 337 wma_handle_disconnect_reason(wma, data->vdev_id, 338 HAL_DEL_STA_REASON_CODE_BTM_DISASSOC_IMMINENT); 339 break; 340 default: 341 return QDF_STATUS_SUCCESS; 342 } 343 344 return QDF_STATUS_SUCCESS; 345 } 346 347 QDF_STATUS 348 cm_handle_scan_ch_list_data(struct cm_roam_scan_ch_resp *data) 349 { 350 struct scheduler_msg sme_msg = {0}; 351 352 sme_msg.type = eWNI_SME_GET_ROAM_SCAN_CH_LIST_EVENT; 353 sme_msg.bodyptr = data; 354 355 if (scheduler_post_message(QDF_MODULE_ID_WMA, 356 QDF_MODULE_ID_SME, 357 QDF_MODULE_ID_SME, &sme_msg)) { 358 wma_err("Failed to post msg to SME"); 359 qdf_mem_free(sme_msg.bodyptr); 360 return -EINVAL; 361 } 362 363 return QDF_STATUS_SUCCESS; 364 } 365 366 #endif 367 368 /** 369 * wma_process_set_pdev_ie_req() - process the pdev set IE req 370 * @wma: Pointer to wma handle 371 * @ie_params: Pointer to IE data. 372 * 373 * Sends the WMI req to set the IE to FW. 374 * 375 * Return: None 376 */ 377 void wma_process_set_pdev_ie_req(tp_wma_handle wma, 378 struct set_ie_param *ie_params) 379 { 380 if (ie_params->ie_type == DOT11_HT_IE) 381 wma_process_set_pdev_ht_ie_req(wma, ie_params); 382 if (ie_params->ie_type == DOT11_VHT_IE) 383 wma_process_set_pdev_vht_ie_req(wma, ie_params); 384 385 qdf_mem_free(ie_params->ie_ptr); 386 } 387 388 /** 389 * wma_process_set_pdev_ht_ie_req() - sends HT IE data to FW 390 * @wma: Pointer to wma handle 391 * @ie_params: Pointer to IE data. 392 * @nss: Nss values to prepare the HT IE. 393 * 394 * Sends the WMI req to set the HT IE to FW. 395 * 396 * Return: None 397 */ 398 void wma_process_set_pdev_ht_ie_req(tp_wma_handle wma, 399 struct set_ie_param *ie_params) 400 { 401 QDF_STATUS status; 402 wmi_pdev_set_ht_ie_cmd_fixed_param *cmd; 403 wmi_buf_t buf; 404 uint16_t len; 405 uint16_t ie_len_pad; 406 uint8_t *buf_ptr; 407 408 len = sizeof(*cmd) + WMI_TLV_HDR_SIZE; 409 ie_len_pad = roundup(ie_params->ie_len, sizeof(uint32_t)); 410 len += ie_len_pad; 411 412 buf = wmi_buf_alloc(wma->wmi_handle, len); 413 if (!buf) 414 return; 415 416 cmd = (wmi_pdev_set_ht_ie_cmd_fixed_param *)wmi_buf_data(buf); 417 WMITLV_SET_HDR(&cmd->tlv_header, 418 WMITLV_TAG_STRUC_wmi_pdev_set_ht_ie_cmd_fixed_param, 419 WMITLV_GET_STRUCT_TLVLEN( 420 wmi_pdev_set_ht_ie_cmd_fixed_param)); 421 cmd->reserved0 = 0; 422 cmd->ie_len = ie_params->ie_len; 423 cmd->tx_streams = ie_params->nss; 424 cmd->rx_streams = ie_params->nss; 425 wma_debug("Setting pdev HT ie with Nss = %u", ie_params->nss); 426 buf_ptr = (uint8_t *)cmd + sizeof(*cmd); 427 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE, ie_len_pad); 428 if (ie_params->ie_len) { 429 qdf_mem_copy(buf_ptr + WMI_TLV_HDR_SIZE, 430 (uint8_t *)ie_params->ie_ptr, 431 ie_params->ie_len); 432 } 433 434 status = wmi_unified_cmd_send(wma->wmi_handle, buf, len, 435 WMI_PDEV_SET_HT_CAP_IE_CMDID); 436 if (QDF_IS_STATUS_ERROR(status)) 437 wmi_buf_free(buf); 438 } 439 440 /** 441 * wma_process_set_pdev_vht_ie_req() - sends VHT IE data to FW 442 * @wma: Pointer to wma handle 443 * @ie_params: Pointer to IE data. 444 * @nss: Nss values to prepare the VHT IE. 445 * 446 * Sends the WMI req to set the VHT IE to FW. 447 * 448 * Return: None 449 */ 450 void wma_process_set_pdev_vht_ie_req(tp_wma_handle wma, 451 struct set_ie_param *ie_params) 452 { 453 QDF_STATUS status; 454 wmi_pdev_set_vht_ie_cmd_fixed_param *cmd; 455 wmi_buf_t buf; 456 uint16_t len; 457 uint16_t ie_len_pad; 458 uint8_t *buf_ptr; 459 460 len = sizeof(*cmd) + WMI_TLV_HDR_SIZE; 461 ie_len_pad = roundup(ie_params->ie_len, sizeof(uint32_t)); 462 len += ie_len_pad; 463 464 buf = wmi_buf_alloc(wma->wmi_handle, len); 465 if (!buf) 466 return; 467 468 cmd = (wmi_pdev_set_vht_ie_cmd_fixed_param *)wmi_buf_data(buf); 469 WMITLV_SET_HDR(&cmd->tlv_header, 470 WMITLV_TAG_STRUC_wmi_pdev_set_vht_ie_cmd_fixed_param, 471 WMITLV_GET_STRUCT_TLVLEN( 472 wmi_pdev_set_vht_ie_cmd_fixed_param)); 473 cmd->reserved0 = 0; 474 cmd->ie_len = ie_params->ie_len; 475 cmd->tx_streams = ie_params->nss; 476 cmd->rx_streams = ie_params->nss; 477 wma_debug("Setting pdev VHT ie with Nss = %u", ie_params->nss); 478 buf_ptr = (uint8_t *)cmd + sizeof(*cmd); 479 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE, ie_len_pad); 480 if (ie_params->ie_len) { 481 qdf_mem_copy(buf_ptr + WMI_TLV_HDR_SIZE, 482 (uint8_t *)ie_params->ie_ptr, ie_params->ie_len); 483 } 484 485 status = wmi_unified_cmd_send(wma->wmi_handle, buf, len, 486 WMI_PDEV_SET_VHT_CAP_IE_CMDID); 487 if (QDF_IS_STATUS_ERROR(status)) 488 wmi_buf_free(buf); 489 } 490 491 #define MAX_VDEV_ROAM_SCAN_PARAMS 2 492 /* params being sent: 493 * wmi_vdev_param_bmiss_first_bcnt 494 * wmi_vdev_param_bmiss_final_bcnt 495 */ 496 497 /** 498 * wma_roam_scan_bmiss_cnt() - set bmiss count to fw 499 * @wma_handle: wma handle 500 * @first_bcnt: first bmiss count 501 * @final_bcnt: final bmiss count 502 * @vdev_id: vdev id 503 * 504 * set first & final biss count to fw. 505 * 506 * Return: QDF status 507 */ 508 QDF_STATUS wma_roam_scan_bmiss_cnt(tp_wma_handle wma_handle, 509 A_INT32 first_bcnt, 510 A_UINT32 final_bcnt, uint32_t vdev_id) 511 { 512 QDF_STATUS status = QDF_STATUS_SUCCESS; 513 struct dev_set_param setparam[MAX_VDEV_ROAM_SCAN_PARAMS] = {}; 514 uint8_t index = 0; 515 516 wma_debug("first_bcnt: %d, final_bcnt: %d", first_bcnt, final_bcnt); 517 518 status = mlme_check_index_setparam(setparam, 519 wmi_vdev_param_bmiss_first_bcnt, 520 first_bcnt, index++, 521 MAX_VDEV_ROAM_SCAN_PARAMS); 522 if (QDF_IS_STATUS_ERROR(status)) { 523 wma_err("failed to set wmi_vdev_param_bmiss_first_bcnt"); 524 goto error; 525 } 526 status = mlme_check_index_setparam(setparam, 527 wmi_vdev_param_bmiss_final_bcnt, 528 final_bcnt, index++, 529 MAX_VDEV_ROAM_SCAN_PARAMS); 530 if (QDF_IS_STATUS_ERROR(status)) { 531 wma_err("failed to set wmi_vdev_param_bmiss_final_bcnt"); 532 goto error; 533 } 534 status = wma_send_multi_pdev_vdev_set_params(MLME_VDEV_SETPARAM, 535 vdev_id, setparam, index); 536 if (QDF_IS_STATUS_ERROR(status)) 537 wma_err("Failed to set BMISS FIRST and FINAL vdev set params"); 538 error: 539 return status; 540 } 541 542 #ifdef WLAN_FEATURE_ROAM_OFFLOAD 543 void 544 wma_send_roam_preauth_status(tp_wma_handle wma_handle, 545 struct wmi_roam_auth_status_params *params) 546 { 547 QDF_STATUS status; 548 struct wmi_unified *wmi_handle; 549 550 if (wma_validate_handle(wma_handle)) 551 return; 552 553 wmi_handle = wma_handle->wmi_handle; 554 if (wmi_validate_handle(wmi_handle)) 555 return; 556 557 status = wmi_unified_send_roam_preauth_status(wmi_handle, params); 558 if (QDF_IS_STATUS_ERROR(status)) 559 wma_err("failed to send disconnect roam preauth status"); 560 } 561 #endif 562 563 #ifdef WLAN_FEATURE_ROAM_OFFLOAD 564 /** 565 * wma_delete_bss_peer() Delete bss peer/s for Non ML interface 566 * @wma: Global WMA Handle 567 * @vdev_id: vdev id 568 * 569 * This function will perform cleanup of the peer corresponds 570 * to given vdev_id 571 * 572 * Return: QDF status 573 */ 574 static 575 QDF_STATUS wma_delete_bss_peer(tp_wma_handle wma, 576 uint8_t vdev_id) 577 { 578 tDeleteStaParams *del_sta_params; 579 580 del_sta_params = qdf_mem_malloc(sizeof(*del_sta_params)); 581 if (!del_sta_params) 582 return QDF_STATUS_E_NOMEM; 583 584 del_sta_params->smesessionId = vdev_id; 585 wma_delete_sta(wma, del_sta_params); 586 wma_delete_bss(wma, vdev_id); 587 588 return QDF_STATUS_SUCCESS; 589 } 590 591 #ifdef WLAN_FEATURE_11BE_MLO 592 /** 593 * wma_delete_all_peers() - Delete all bss peer/s 594 * @wma: Global WMA Handle 595 * @vdev_id: vdev id 596 * @del_sta_params: parameters required for del sta request 597 * 598 * This function will perform deleting of all the link peers 599 * after self roaming. 600 * 601 * Return: None 602 */ 603 static QDF_STATUS 604 wma_delete_all_peers(tp_wma_handle wma, 605 uint8_t vdev_id) 606 { 607 struct wlan_objmgr_vdev *vdev; 608 struct wlan_mlo_dev_context *mlo_dev_ctx; 609 uint8_t i; 610 uint8_t link_vdev_id; 611 tDeleteStaParams *del_sta_params; 612 QDF_STATUS status = QDF_STATUS_SUCCESS; 613 struct qdf_mac_addr bssid; 614 struct qdf_mac_addr *mld_addr; 615 616 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(wma->psoc, vdev_id, 617 WLAN_MLME_OBJMGR_ID); 618 if (!vdev) { 619 mlme_err("vdev object is NULL for vdev %d", vdev_id); 620 return QDF_STATUS_E_NULL_VALUE; 621 } 622 623 mlo_dev_ctx = vdev->mlo_dev_ctx; 624 if (!mlo_dev_ctx) { 625 mld_addr = 626 (struct qdf_mac_addr *)wlan_vdev_mlme_get_mldaddr(vdev); 627 /* It's not a ML interface*/ 628 if (qdf_is_macaddr_zero(mld_addr)) { 629 mlme_debug("Non-ML STA vdev_id: %d", vdev_id); 630 status = wma_delete_bss_peer(wma, vdev_id); 631 goto end; 632 } 633 634 mlme_err("mlo_dev_ctx object is NULL for vdev %d", vdev_id); 635 status = QDF_STATUS_E_NULL_VALUE; 636 goto end; 637 } 638 639 for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) { 640 if (!mlo_dev_ctx->wlan_vdev_list[i]) 641 continue; 642 643 if (QDF_IS_STATUS_ERROR(wlan_vdev_get_bss_peer_mac( 644 mlo_dev_ctx->wlan_vdev_list[i], 645 &bssid))) { 646 pe_debug("bss peer is not present on vdev id %d, no need to cleanup", 647 wlan_vdev_get_id( 648 mlo_dev_ctx->wlan_vdev_list[i])); 649 continue; 650 } 651 652 del_sta_params = qdf_mem_malloc(sizeof(*del_sta_params)); 653 if (!del_sta_params) { 654 status = QDF_STATUS_E_NOMEM; 655 goto end; 656 } 657 lim_mlo_roam_peer_disconn_del(mlo_dev_ctx->wlan_vdev_list[i]); 658 qdf_mem_zero(del_sta_params, sizeof(*del_sta_params)); 659 link_vdev_id = wlan_vdev_get_id(mlo_dev_ctx->wlan_vdev_list[i]); 660 if (link_vdev_id == WLAN_INVALID_VDEV_ID) { 661 mlme_err("invalid vdev id"); 662 status = QDF_STATUS_E_INVAL; 663 goto end; 664 } 665 del_sta_params->smesessionId = link_vdev_id; 666 wma_delete_sta(wma, del_sta_params); 667 wma_delete_bss(wma, link_vdev_id); 668 } 669 670 end: 671 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_OBJMGR_ID); 672 return status; 673 } 674 #else 675 static inline QDF_STATUS 676 wma_delete_all_peers(tp_wma_handle wma, 677 uint8_t vdev_id) 678 { 679 return wma_delete_bss_peer(wma, vdev_id); 680 } 681 #endif 682 /** 683 * wma_roam_update_vdev() - Update the STA and BSS 684 * @wma: Global WMA Handle 685 * @roam_synch_ind_ptr: Information needed for roam sync propagation 686 * 687 * This function will perform all the vdev related operations with 688 * respect to the self sta and the peer after roaming and completes 689 * the roam synch propagation with respect to WMA layer. 690 * 691 * Return: None 692 */ 693 static void 694 wma_roam_update_vdev(tp_wma_handle wma, 695 struct roam_offload_synch_ind *roam_synch_ind_ptr, 696 uint8_t roamed_vdev_id) 697 { 698 tAddStaParams *add_sta_params; 699 uint8_t vdev_id, *bssid; 700 int32_t uc_cipher, cipher_cap; 701 bool is_assoc_peer = false; 702 struct qdf_mac_addr mac_addr; 703 QDF_STATUS status = QDF_STATUS_SUCCESS; 704 705 vdev_id = roamed_vdev_id; 706 wma->interfaces[vdev_id].nss = roam_synch_ind_ptr->nss; 707 708 /* update channel width */ 709 wma->interfaces[vdev_id].chan_width = 710 roam_synch_ind_ptr->chan_width; 711 /* Fill link freq from roam_synch_ind */ 712 if (is_multi_link_roam(roam_synch_ind_ptr)) 713 wma->interfaces[vdev_id].ch_freq = 714 mlo_roam_get_chan_freq(vdev_id, roam_synch_ind_ptr); 715 else 716 wma->interfaces[vdev_id].ch_freq = 717 roam_synch_ind_ptr->chan_freq; 718 719 add_sta_params = qdf_mem_malloc(sizeof(*add_sta_params)); 720 if (!add_sta_params) { 721 return; 722 } 723 724 if (is_multi_link_roam(roam_synch_ind_ptr)) 725 mlo_get_sta_link_mac_addr(vdev_id, roam_synch_ind_ptr, 726 &mac_addr); 727 else 728 mac_addr = roam_synch_ind_ptr->bssid; 729 730 qdf_mem_zero(add_sta_params, sizeof(*add_sta_params)); 731 732 /* With self roaming on multi link AP, as the same 733 * peer already exists, new peer creation fails 734 * To handle this delete all link peers, 735 * while doing roam sync on first link. 736 */ 737 if (!is_multi_link_roam(roam_synch_ind_ptr) || 738 wlan_vdev_mlme_get_is_mlo_link(wma->psoc, vdev_id) || 739 mlo_get_single_link_ml_roaming(wma->psoc, vdev_id)) { 740 status = wma_delete_all_peers(wma, vdev_id); 741 if (QDF_IS_STATUS_ERROR(status)) 742 goto end; 743 } 744 745 add_sta_params->staType = STA_ENTRY_SELF; 746 add_sta_params->smesessionId = vdev_id; 747 qdf_mem_copy(&add_sta_params->bssId, &mac_addr, 748 QDF_MAC_ADDR_SIZE); 749 add_sta_params->assocId = roam_synch_ind_ptr->aid; 750 751 bssid = wma_get_vdev_bssid(wma->interfaces[vdev_id].vdev); 752 if (!bssid) { 753 wma_err("Failed to get bssid for vdev_%d", vdev_id); 754 return; 755 } 756 757 is_assoc_peer = wlan_vdev_mlme_get_is_mlo_vdev(wma->psoc, vdev_id); 758 if (is_multi_link_roam(roam_synch_ind_ptr)) { 759 wma_create_peer(wma, mac_addr.bytes, 760 WMI_PEER_TYPE_DEFAULT, vdev_id, 761 roam_synch_ind_ptr->bssid.bytes, 762 is_assoc_peer); 763 } else { 764 wma_create_peer(wma, mac_addr.bytes, 765 WMI_PEER_TYPE_DEFAULT, 766 vdev_id, 767 NULL, 768 is_assoc_peer); 769 } 770 771 if (is_multi_link_roam(roam_synch_ind_ptr)) 772 lim_roam_mlo_create_peer(wma->mac_context, 773 roam_synch_ind_ptr, 774 vdev_id, 775 mac_addr.bytes); 776 777 if (wlan_vdev_mlme_get_opmode(wma->interfaces[vdev_id].vdev) == 778 QDF_STA_MODE) 779 wlan_cdp_set_peer_freq(wma->psoc, mac_addr.bytes, 780 wma->interfaces[vdev_id].ch_freq, 781 vdev_id); 782 783 /* Update new peer's uc cipher */ 784 uc_cipher = wlan_crypto_get_param(wma->interfaces[vdev_id].vdev, 785 WLAN_CRYPTO_PARAM_UCAST_CIPHER); 786 cipher_cap = wlan_crypto_get_param(wma->interfaces[vdev_id].vdev, 787 WLAN_CRYPTO_PARAM_CIPHER_CAP); 788 wma_set_peer_ucast_cipher(mac_addr.bytes, uc_cipher, 789 cipher_cap); 790 wma_add_bss_lfr3(wma, roam_synch_ind_ptr->add_bss_params); 791 wma_add_sta(wma, add_sta_params); 792 qdf_mem_copy(bssid, mac_addr.bytes, 793 QDF_MAC_ADDR_SIZE); 794 lim_fill_roamed_peer_twt_caps(wma->mac_context, vdev_id, 795 roam_synch_ind_ptr); 796 end: 797 qdf_mem_free(add_sta_params); 798 } 799 800 static void wma_update_phymode_on_roam(tp_wma_handle wma, 801 struct qdf_mac_addr *bssid, 802 wmi_channel *chan, 803 struct wma_txrx_node *iface) 804 { 805 enum wlan_phymode bss_phymode; 806 struct wlan_channel *des_chan; 807 struct wlan_channel *bss_chan; 808 struct vdev_mlme_obj *vdev_mlme; 809 uint8_t channel; 810 struct wlan_objmgr_pdev *pdev = NULL; 811 qdf_freq_t sec_ch_2g_freq = 0; 812 struct ch_params ch_params = {0}; 813 814 vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(iface->vdev); 815 if (!vdev_mlme) 816 return; 817 818 pdev = wlan_vdev_get_pdev(vdev_mlme->vdev); 819 820 channel = wlan_reg_freq_to_chan(pdev, iface->ch_freq); 821 if (chan) 822 bss_phymode = 823 wma_fw_to_host_phymode(WMI_GET_CHANNEL_MODE(chan)); 824 else 825 wma_get_phy_mode_cb(iface->ch_freq, 826 iface->chan_width, &bss_phymode); 827 828 /* Update vdev mlme channel info after roaming */ 829 des_chan = wlan_vdev_mlme_get_des_chan(iface->vdev); 830 bss_chan = wlan_vdev_mlme_get_bss_chan(iface->vdev); 831 des_chan->ch_phymode = bss_phymode; 832 des_chan->ch_width = iface->chan_width; 833 if (chan) { 834 des_chan->ch_freq = chan->mhz; 835 ch_params.ch_width = des_chan->ch_width; 836 if (wlan_reg_is_24ghz_ch_freq(des_chan->ch_freq) && 837 des_chan->ch_width == CH_WIDTH_40MHZ && 838 chan->band_center_freq1) { 839 if (des_chan->ch_freq < chan->band_center_freq1) 840 sec_ch_2g_freq = des_chan->ch_freq + 20; 841 else 842 sec_ch_2g_freq = des_chan->ch_freq - 20; 843 } 844 wlan_reg_set_channel_params_for_pwrmode(pdev, des_chan->ch_freq, 845 sec_ch_2g_freq, 846 &ch_params, 847 REG_CURRENT_PWR_MODE); 848 if (ch_params.ch_width != des_chan->ch_width || 849 ch_params.mhz_freq_seg0 != chan->band_center_freq1 || 850 ch_params.mhz_freq_seg1 != chan->band_center_freq2) 851 wma_err("ch mismatch host & fw bw (%d %d) seg0 (%d, %d) seg1 (%d, %d)", 852 ch_params.ch_width, des_chan->ch_width, 853 ch_params.mhz_freq_seg0, 854 chan->band_center_freq1, 855 ch_params.mhz_freq_seg1, 856 chan->band_center_freq2); 857 des_chan->ch_cfreq1 = ch_params.mhz_freq_seg0; 858 des_chan->ch_cfreq2 = ch_params.mhz_freq_seg1; 859 des_chan->ch_width = ch_params.ch_width; 860 } else { 861 wma_err("LFR3: invalid chan"); 862 } 863 qdf_mem_copy(bss_chan, des_chan, sizeof(struct wlan_channel)); 864 865 /* Till conversion is not done in WMI we need to fill fw phy mode */ 866 vdev_mlme->mgmt.generic.phy_mode = wmi_host_to_fw_phymode(bss_phymode); 867 868 /* update new phymode to peer */ 869 wma_objmgr_set_peer_mlme_phymode(wma, bssid->bytes, bss_phymode); 870 871 wma_debug("LFR3: new phymode %d freq %d (bw %d, %d %d)", 872 bss_phymode, des_chan->ch_freq, des_chan->ch_width, 873 des_chan->ch_cfreq1, des_chan->ch_cfreq2); 874 } 875 876 /** 877 * wma_set_ric_req() - set ric request element 878 * @wma: wma handle 879 * @msg: message 880 * @is_add_ts: is addts required 881 * 882 * This function sets ric request element for 11r roaming. 883 * 884 * Return: none 885 */ 886 void wma_set_ric_req(tp_wma_handle wma, void *msg, uint8_t is_add_ts) 887 { 888 if (!wma) { 889 wma_err("wma handle is NULL"); 890 return; 891 } 892 893 wmi_unified_set_ric_req_cmd(wma->wmi_handle, msg, is_add_ts); 894 } 895 #endif /* WLAN_FEATURE_ROAM_OFFLOAD */ 896 897 #ifdef FEATURE_RSSI_MONITOR 898 QDF_STATUS wma_set_rssi_monitoring(tp_wma_handle wma, 899 struct rssi_monitor_param *req) 900 { 901 if (!wma) { 902 wma_err("wma handle is NULL"); 903 return QDF_STATUS_E_INVAL; 904 } 905 906 return wmi_unified_set_rssi_monitoring_cmd(wma->wmi_handle, req); 907 } 908 909 /** 910 * wma_rssi_breached_event_handler() - rssi breached event handler 911 * @handle: wma handle 912 * @cmd_param_info: event handler data 913 * @len: length of @cmd_param_info 914 * 915 * Return: 0 on success; error number otherwise 916 */ 917 int wma_rssi_breached_event_handler(void *handle, 918 u_int8_t *cmd_param_info, u_int32_t len) 919 { 920 WMI_RSSI_BREACH_EVENTID_param_tlvs *param_buf; 921 wmi_rssi_breach_event_fixed_param *event; 922 struct rssi_breach_event rssi; 923 struct mac_context *mac = cds_get_context(QDF_MODULE_ID_PE); 924 tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA); 925 926 if (!mac || !wma) { 927 wma_err("Invalid mac/wma context"); 928 return -EINVAL; 929 } 930 if (!mac->sme.rssi_threshold_breached_cb) { 931 wma_err("Callback not registered"); 932 return -EINVAL; 933 } 934 param_buf = (WMI_RSSI_BREACH_EVENTID_param_tlvs *)cmd_param_info; 935 if (!param_buf) { 936 wma_err("Invalid rssi breached event"); 937 return -EINVAL; 938 } 939 event = param_buf->fixed_param; 940 941 rssi.request_id = event->request_id; 942 rssi.session_id = event->vdev_id; 943 if (wmi_service_enabled(wma->wmi_handle, 944 wmi_service_hw_db2dbm_support)) 945 rssi.curr_rssi = event->rssi; 946 else 947 rssi.curr_rssi = event->rssi + WMA_TGT_NOISE_FLOOR_DBM; 948 WMI_MAC_ADDR_TO_CHAR_ARRAY(&event->bssid, rssi.curr_bssid.bytes); 949 950 wma_debug("req_id: %u vdev_id: %d curr_rssi: %d", 951 rssi.request_id, rssi.session_id, rssi.curr_rssi); 952 wma_debug("curr_bssid: "QDF_MAC_ADDR_FMT, 953 QDF_MAC_ADDR_REF(rssi.curr_bssid.bytes)); 954 955 mac->sme.rssi_threshold_breached_cb(mac->hdd_handle, &rssi); 956 wma_debug("Invoke HDD rssi breached callback"); 957 return 0; 958 } 959 #endif /* FEATURE_RSSI_MONITOR */ 960 961 QDF_STATUS wma_pre_chan_switch_setup(uint8_t vdev_id) 962 { 963 QDF_STATUS status = QDF_STATUS_SUCCESS; 964 tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA); 965 struct wma_txrx_node *intr; 966 uint16_t beacon_interval_ori; 967 bool restart; 968 uint16_t reduced_beacon_interval; 969 struct vdev_mlme_obj *mlme_obj; 970 struct wlan_objmgr_vdev *vdev; 971 972 if (!wma) { 973 pe_err("wma is NULL"); 974 return QDF_STATUS_E_FAILURE; 975 } 976 intr = &wma->interfaces[vdev_id]; 977 if (!intr) { 978 pe_err("wma txrx node is NULL"); 979 return QDF_STATUS_E_FAILURE; 980 } 981 vdev = intr->vdev; 982 mlme_obj = wlan_vdev_mlme_get_cmpt_obj(vdev); 983 if (!mlme_obj) { 984 pe_err("vdev component object is NULL"); 985 return QDF_STATUS_E_FAILURE; 986 } 987 988 restart = 989 wma_get_channel_switch_in_progress(intr); 990 if (restart && intr->beacon_filter_enabled) 991 wma_remove_beacon_filter(wma, &intr->beacon_filter); 992 993 reduced_beacon_interval = 994 wma->mac_context->sap.SapDfsInfo.reduced_beacon_interval; 995 if (wma_is_vdev_in_ap_mode(wma, vdev_id) && reduced_beacon_interval) { 996 997 998 /* Reduce the beacon interval just before the channel switch. 999 * This would help in reducing the downtime on the STA side 1000 * (which is waiting for beacons from the AP to resume back 1001 * transmission). Switch back the beacon_interval to its 1002 * original value after the channel switch based on the 1003 * timeout. This would ensure there are atleast some beacons 1004 * sent with increased frequency. 1005 */ 1006 1007 wma_debug("Changing beacon interval to %d", 1008 reduced_beacon_interval); 1009 1010 /* Add a timer to reset the beacon interval back*/ 1011 beacon_interval_ori = mlme_obj->proto.generic.beacon_interval; 1012 mlme_obj->proto.generic.beacon_interval = 1013 reduced_beacon_interval; 1014 if (wma_fill_beacon_interval_reset_req(wma, 1015 vdev_id, 1016 beacon_interval_ori, 1017 RESET_BEACON_INTERVAL_TIMEOUT)) { 1018 1019 wma_debug("Failed to fill beacon interval reset req"); 1020 } 1021 } 1022 1023 status = wma_vdev_pre_start(vdev_id, restart); 1024 1025 return status; 1026 } 1027 1028 QDF_STATUS wma_post_chan_switch_setup(uint8_t vdev_id) 1029 { 1030 tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA); 1031 struct wma_txrx_node *intr; 1032 void *soc = cds_get_context(QDF_MODULE_ID_SOC); 1033 struct wlan_channel *des_chan; 1034 cdp_config_param_type val; 1035 1036 if (!wma) { 1037 pe_err("wma is NULL"); 1038 return QDF_STATUS_E_FAILURE; 1039 } 1040 intr = &wma->interfaces[vdev_id]; 1041 if (!intr) { 1042 pe_err("wma txrx node is NULL"); 1043 return QDF_STATUS_E_FAILURE; 1044 } 1045 /* 1046 * Record monitor mode channel here in case HW 1047 * indicate RX PPDU TLV with invalid channel number. 1048 */ 1049 if (intr->type == WMI_VDEV_TYPE_MONITOR) { 1050 des_chan = intr->vdev->vdev_mlme.des_chan; 1051 val.cdp_pdev_param_monitor_chan = des_chan->ch_ieee; 1052 cdp_txrx_set_pdev_param(soc, 1053 wlan_objmgr_pdev_get_pdev_id(wma->pdev), 1054 CDP_MONITOR_CHANNEL, val); 1055 val.cdp_pdev_param_mon_freq = des_chan->ch_freq; 1056 cdp_txrx_set_pdev_param(soc, 1057 wlan_objmgr_pdev_get_pdev_id(wma->pdev), 1058 CDP_MONITOR_FREQUENCY, val); 1059 } 1060 return QDF_STATUS_SUCCESS; 1061 } 1062 1063 #ifdef FEATURE_WLAN_ESE 1064 /** 1065 * wma_plm_start() - plm start request 1066 * @wma: wma handle 1067 * @params: plm request parameters 1068 * 1069 * This function request FW to start PLM. 1070 * 1071 * Return: QDF status 1072 */ 1073 static QDF_STATUS wma_plm_start(tp_wma_handle wma, 1074 struct plm_req_params *params) 1075 { 1076 QDF_STATUS status; 1077 1078 wma_debug("PLM Start"); 1079 1080 status = wmi_unified_plm_start_cmd(wma->wmi_handle, params); 1081 if (QDF_IS_STATUS_ERROR(status)) 1082 return status; 1083 1084 wma->interfaces[params->vdev_id].plm_in_progress = true; 1085 1086 wma_debug("Plm start request sent successfully for vdev %d", 1087 params->vdev_id); 1088 1089 return status; 1090 } 1091 1092 /** 1093 * wma_plm_stop() - plm stop request 1094 * @wma: wma handle 1095 * @params: plm request parameters 1096 * 1097 * This function request FW to stop PLM. 1098 * 1099 * Return: QDF status 1100 */ 1101 static QDF_STATUS wma_plm_stop(tp_wma_handle wma, 1102 struct plm_req_params *params) 1103 { 1104 QDF_STATUS status; 1105 1106 if (!wma->interfaces[params->vdev_id].plm_in_progress) { 1107 wma_err("No active plm req found, skip plm stop req"); 1108 return QDF_STATUS_E_FAILURE; 1109 } 1110 1111 wma_debug("PLM Stop"); 1112 1113 status = wmi_unified_plm_stop_cmd(wma->wmi_handle, params); 1114 if (QDF_IS_STATUS_ERROR(status)) 1115 return status; 1116 1117 wma->interfaces[params->vdev_id].plm_in_progress = false; 1118 1119 wma_debug("Plm stop request sent successfully for vdev %d", 1120 params->vdev_id); 1121 1122 return status; 1123 } 1124 1125 /** 1126 * wma_config_plm() - config PLM 1127 * @wma: wma handle 1128 * @params: plm request parameters 1129 * 1130 * Return: none 1131 */ 1132 void wma_config_plm(tp_wma_handle wma, struct plm_req_params *params) 1133 { 1134 QDF_STATUS ret; 1135 1136 if (!params || !wma) 1137 return; 1138 1139 if (params->enable) 1140 ret = wma_plm_start(wma, params); 1141 else 1142 ret = wma_plm_stop(wma, params); 1143 1144 if (ret) 1145 wma_err("PLM %s failed %d", 1146 params->enable ? "start" : "stop", ret); 1147 } 1148 #endif 1149 1150 #ifdef FEATURE_WLAN_EXTSCAN 1151 /** 1152 * wma_extscan_wow_event_callback() - extscan wow event callback 1153 * @handle: WMA handle 1154 * @event: event buffer 1155 * @len: length of @event buffer 1156 * 1157 * In wow case, the wow event is followed by the payload of the event 1158 * which generated the wow event. 1159 * payload is 4 bytes of length followed by event buffer. the first 4 bytes 1160 * of event buffer is common tlv header, which is a combination 1161 * of tag (higher 2 bytes) and length (lower 2 bytes). The tag is used to 1162 * identify the event which triggered wow event. 1163 * Payload is extracted and converted into generic tlv structure before 1164 * being passed to this function. 1165 * 1166 * @Return: Errno 1167 */ 1168 int wma_extscan_wow_event_callback(void *handle, void *event, uint32_t len) 1169 { 1170 uint32_t tag = WMITLV_GET_TLVTAG(WMITLV_GET_HDR(event)); 1171 1172 switch (tag) { 1173 case WMITLV_TAG_STRUC_wmi_extscan_start_stop_event_fixed_param: 1174 return wma_extscan_start_stop_event_handler(handle, event, len); 1175 1176 case WMITLV_TAG_STRUC_wmi_extscan_operation_event_fixed_param: 1177 return wma_extscan_operations_event_handler(handle, event, len); 1178 1179 case WMITLV_TAG_STRUC_wmi_extscan_table_usage_event_fixed_param: 1180 return wma_extscan_table_usage_event_handler(handle, event, 1181 len); 1182 1183 case WMITLV_TAG_STRUC_wmi_extscan_cached_results_event_fixed_param: 1184 return wma_extscan_cached_results_event_handler(handle, event, 1185 len); 1186 1187 case WMITLV_TAG_STRUC_wmi_extscan_wlan_change_results_event_fixed_param: 1188 return wma_extscan_change_results_event_handler(handle, event, 1189 len); 1190 1191 case WMITLV_TAG_STRUC_wmi_extscan_hotlist_match_event_fixed_param: 1192 return wma_extscan_hotlist_match_event_handler(handle, event, 1193 len); 1194 1195 case WMITLV_TAG_STRUC_wmi_extscan_capabilities_event_fixed_param: 1196 return wma_extscan_capabilities_event_handler(handle, event, 1197 len); 1198 1199 default: 1200 wma_err("Unknown tag: %d", tag); 1201 return 0; 1202 } 1203 } 1204 1205 /** 1206 * wma_register_extscan_event_handler() - register extscan event handler 1207 * @wma_handle: wma handle 1208 * 1209 * This function register extscan related event handlers. 1210 * 1211 * Return: none 1212 */ 1213 void wma_register_extscan_event_handler(tp_wma_handle wma_handle) 1214 { 1215 if (wma_validate_handle(wma_handle)) 1216 return; 1217 1218 wmi_unified_register_event_handler(wma_handle->wmi_handle, 1219 wmi_extscan_start_stop_event_id, 1220 wma_extscan_start_stop_event_handler, 1221 WMA_RX_SERIALIZER_CTX); 1222 1223 wmi_unified_register_event_handler(wma_handle->wmi_handle, 1224 wmi_extscan_capabilities_event_id, 1225 wma_extscan_capabilities_event_handler, 1226 WMA_RX_SERIALIZER_CTX); 1227 1228 wmi_unified_register_event_handler(wma_handle->wmi_handle, 1229 wmi_extscan_hotlist_match_event_id, 1230 wma_extscan_hotlist_match_event_handler, 1231 WMA_RX_SERIALIZER_CTX); 1232 1233 wmi_unified_register_event_handler(wma_handle->wmi_handle, 1234 wmi_extscan_wlan_change_results_event_id, 1235 wma_extscan_change_results_event_handler, 1236 WMA_RX_SERIALIZER_CTX); 1237 1238 wmi_unified_register_event_handler(wma_handle->wmi_handle, 1239 wmi_extscan_operation_event_id, 1240 wma_extscan_operations_event_handler, 1241 WMA_RX_SERIALIZER_CTX); 1242 wmi_unified_register_event_handler(wma_handle->wmi_handle, 1243 wmi_extscan_table_usage_event_id, 1244 wma_extscan_table_usage_event_handler, 1245 WMA_RX_SERIALIZER_CTX); 1246 1247 wmi_unified_register_event_handler(wma_handle->wmi_handle, 1248 wmi_extscan_cached_results_event_id, 1249 wma_extscan_cached_results_event_handler, 1250 WMA_RX_SERIALIZER_CTX); 1251 1252 wmi_unified_register_event_handler(wma_handle->wmi_handle, 1253 wmi_passpoint_match_event_id, 1254 wma_passpoint_match_event_handler, 1255 WMA_RX_SERIALIZER_CTX); 1256 } 1257 1258 /** 1259 * wma_extscan_start_stop_event_handler() - extscan start/stop event handler 1260 * @handle: wma handle 1261 * @cmd_param_info: event buffer 1262 * @len: data length 1263 * 1264 * This function handles different extscan related commands 1265 * like start/stop/get results etc and indicate to upper layers. 1266 * 1267 * Return: 0 for success or error code. 1268 */ 1269 int wma_extscan_start_stop_event_handler(void *handle, 1270 uint8_t *cmd_param_info, 1271 uint32_t len) 1272 { 1273 WMI_EXTSCAN_START_STOP_EVENTID_param_tlvs *param_buf; 1274 wmi_extscan_start_stop_event_fixed_param *event; 1275 struct sir_extscan_generic_response *extscan_ind; 1276 uint16_t event_type; 1277 struct mac_context *mac = cds_get_context(QDF_MODULE_ID_PE); 1278 1279 if (!mac) 1280 return -EINVAL; 1281 1282 if (!mac->sme.ext_scan_ind_cb) { 1283 wma_err("Callback not registered"); 1284 return -EINVAL; 1285 } 1286 param_buf = (WMI_EXTSCAN_START_STOP_EVENTID_param_tlvs *) 1287 cmd_param_info; 1288 if (!param_buf) { 1289 wma_err("Invalid extscan event"); 1290 return -EINVAL; 1291 } 1292 event = param_buf->fixed_param; 1293 extscan_ind = qdf_mem_malloc(sizeof(*extscan_ind)); 1294 if (!extscan_ind) 1295 return -ENOMEM; 1296 1297 switch (event->command) { 1298 case WMI_EXTSCAN_START_CMDID: 1299 event_type = eSIR_EXTSCAN_START_RSP; 1300 extscan_ind->status = event->status; 1301 extscan_ind->request_id = event->request_id; 1302 break; 1303 case WMI_EXTSCAN_STOP_CMDID: 1304 event_type = eSIR_EXTSCAN_STOP_RSP; 1305 extscan_ind->status = event->status; 1306 extscan_ind->request_id = event->request_id; 1307 break; 1308 case WMI_EXTSCAN_CONFIGURE_WLAN_CHANGE_MONITOR_CMDID: 1309 extscan_ind->status = event->status; 1310 extscan_ind->request_id = event->request_id; 1311 if (event->mode == WMI_EXTSCAN_MODE_STOP) 1312 event_type = 1313 eSIR_EXTSCAN_RESET_SIGNIFICANT_WIFI_CHANGE_RSP; 1314 else 1315 event_type = 1316 eSIR_EXTSCAN_SET_SIGNIFICANT_WIFI_CHANGE_RSP; 1317 break; 1318 case WMI_EXTSCAN_CONFIGURE_HOTLIST_MONITOR_CMDID: 1319 extscan_ind->status = event->status; 1320 extscan_ind->request_id = event->request_id; 1321 if (event->mode == WMI_EXTSCAN_MODE_STOP) 1322 event_type = eSIR_EXTSCAN_RESET_BSSID_HOTLIST_RSP; 1323 else 1324 event_type = eSIR_EXTSCAN_SET_BSSID_HOTLIST_RSP; 1325 break; 1326 case WMI_EXTSCAN_GET_CACHED_RESULTS_CMDID: 1327 extscan_ind->status = event->status; 1328 extscan_ind->request_id = event->request_id; 1329 event_type = eSIR_EXTSCAN_CACHED_RESULTS_RSP; 1330 break; 1331 case WMI_EXTSCAN_CONFIGURE_HOTLIST_SSID_MONITOR_CMDID: 1332 extscan_ind->status = event->status; 1333 extscan_ind->request_id = event->request_id; 1334 if (event->mode == WMI_EXTSCAN_MODE_STOP) 1335 event_type = 1336 eSIR_EXTSCAN_RESET_SSID_HOTLIST_RSP; 1337 else 1338 event_type = 1339 eSIR_EXTSCAN_SET_SSID_HOTLIST_RSP; 1340 break; 1341 default: 1342 wma_err("Unknown event(%d) from target", event->status); 1343 qdf_mem_free(extscan_ind); 1344 return -EINVAL; 1345 } 1346 mac->sme.ext_scan_ind_cb(mac->hdd_handle, event_type, extscan_ind); 1347 wma_debug("sending event to umac for requestid %u with status %d", 1348 extscan_ind->request_id, extscan_ind->status); 1349 qdf_mem_free(extscan_ind); 1350 return 0; 1351 } 1352 1353 /** 1354 * wma_extscan_operations_event_handler() - extscan operation event handler 1355 * @handle: wma handle 1356 * @cmd_param_info: event buffer 1357 * @len: length 1358 * 1359 * This function handles different operations related event and indicate 1360 * upper layers with appropriate callback. 1361 * 1362 * Return: 0 for success or error code. 1363 */ 1364 int wma_extscan_operations_event_handler(void *handle, 1365 uint8_t *cmd_param_info, 1366 uint32_t len) 1367 { 1368 tp_wma_handle wma = (tp_wma_handle) handle; 1369 WMI_EXTSCAN_OPERATION_EVENTID_param_tlvs *param_buf; 1370 wmi_extscan_operation_event_fixed_param *oprn_event; 1371 tSirExtScanOnScanEventIndParams *oprn_ind; 1372 uint32_t cnt; 1373 struct mac_context *mac = cds_get_context(QDF_MODULE_ID_PE); 1374 1375 if (!mac) 1376 return -EINVAL; 1377 1378 if (!mac->sme.ext_scan_ind_cb) { 1379 wma_err("Callback not registered"); 1380 return -EINVAL; 1381 } 1382 param_buf = (WMI_EXTSCAN_OPERATION_EVENTID_param_tlvs *) 1383 cmd_param_info; 1384 if (!param_buf) { 1385 wma_err("Invalid scan operation event"); 1386 return -EINVAL; 1387 } 1388 oprn_event = param_buf->fixed_param; 1389 oprn_ind = qdf_mem_malloc(sizeof(*oprn_ind)); 1390 if (!oprn_ind) 1391 return -ENOMEM; 1392 1393 oprn_ind->requestId = oprn_event->request_id; 1394 1395 switch (oprn_event->event) { 1396 case WMI_EXTSCAN_BUCKET_COMPLETED_EVENT: 1397 oprn_ind->status = 0; 1398 goto exit_handler; 1399 case WMI_EXTSCAN_CYCLE_STARTED_EVENT: 1400 wma_debug("received WMI_EXTSCAN_CYCLE_STARTED_EVENT"); 1401 1402 if (oprn_event->num_buckets > param_buf->num_bucket_id) { 1403 wma_err("FW mesg num_buk %d more than TLV hdr %d", 1404 oprn_event->num_buckets, 1405 param_buf->num_bucket_id); 1406 qdf_mem_free(oprn_ind); 1407 return -EINVAL; 1408 } 1409 1410 cds_host_diag_log_work(&wma->extscan_wake_lock, 1411 WMA_EXTSCAN_CYCLE_WAKE_LOCK_DURATION, 1412 WIFI_POWER_EVENT_WAKELOCK_EXT_SCAN); 1413 qdf_wake_lock_timeout_acquire(&wma->extscan_wake_lock, 1414 WMA_EXTSCAN_CYCLE_WAKE_LOCK_DURATION); 1415 oprn_ind->scanEventType = WIFI_EXTSCAN_CYCLE_STARTED_EVENT; 1416 oprn_ind->status = 0; 1417 oprn_ind->buckets_scanned = 0; 1418 for (cnt = 0; cnt < oprn_event->num_buckets; cnt++) 1419 oprn_ind->buckets_scanned |= 1420 (1 << param_buf->bucket_id[cnt]); 1421 wma_debug("num_buckets %u request_id %u buckets_scanned %u", 1422 oprn_event->num_buckets, oprn_ind->requestId, 1423 oprn_ind->buckets_scanned); 1424 break; 1425 case WMI_EXTSCAN_CYCLE_COMPLETED_EVENT: 1426 wma_debug("received WMI_EXTSCAN_CYCLE_COMPLETED_EVENT"); 1427 qdf_wake_lock_release(&wma->extscan_wake_lock, 1428 WIFI_POWER_EVENT_WAKELOCK_EXT_SCAN); 1429 oprn_ind->scanEventType = WIFI_EXTSCAN_CYCLE_COMPLETED_EVENT; 1430 oprn_ind->status = 0; 1431 /* Set bucket scanned mask to zero on cycle complete */ 1432 oprn_ind->buckets_scanned = 0; 1433 break; 1434 case WMI_EXTSCAN_BUCKET_STARTED_EVENT: 1435 wma_debug("received WMI_EXTSCAN_BUCKET_STARTED_EVENT"); 1436 oprn_ind->scanEventType = WIFI_EXTSCAN_BUCKET_STARTED_EVENT; 1437 oprn_ind->status = 0; 1438 goto exit_handler; 1439 case WMI_EXTSCAN_THRESHOLD_NUM_SCANS: 1440 wma_debug("received WMI_EXTSCAN_THRESHOLD_NUM_SCANS"); 1441 oprn_ind->scanEventType = WIFI_EXTSCAN_THRESHOLD_NUM_SCANS; 1442 oprn_ind->status = 0; 1443 break; 1444 case WMI_EXTSCAN_THRESHOLD_PERCENT: 1445 wma_debug("received WMI_EXTSCAN_THRESHOLD_PERCENT"); 1446 oprn_ind->scanEventType = WIFI_EXTSCAN_THRESHOLD_PERCENT; 1447 oprn_ind->status = 0; 1448 break; 1449 default: 1450 wma_err("Unknown event(%d) from target", oprn_event->event); 1451 qdf_mem_free(oprn_ind); 1452 return -EINVAL; 1453 } 1454 mac->sme.ext_scan_ind_cb(mac->hdd_handle, 1455 eSIR_EXTSCAN_SCAN_PROGRESS_EVENT_IND, oprn_ind); 1456 wma_debug("sending scan progress event to hdd"); 1457 exit_handler: 1458 qdf_mem_free(oprn_ind); 1459 return 0; 1460 } 1461 1462 /** 1463 * wma_extscan_table_usage_event_handler() - extscan table usage event handler 1464 * @handle: wma handle 1465 * @cmd_param_info: event buffer 1466 * @len: length 1467 * 1468 * This function handles table usage related event and indicate 1469 * upper layers with appropriate callback. 1470 * 1471 * Return: 0 for success or error code. 1472 */ 1473 int wma_extscan_table_usage_event_handler(void *handle, 1474 uint8_t *cmd_param_info, 1475 uint32_t len) 1476 { 1477 WMI_EXTSCAN_TABLE_USAGE_EVENTID_param_tlvs *param_buf; 1478 wmi_extscan_table_usage_event_fixed_param *event; 1479 tSirExtScanResultsAvailableIndParams *tbl_usg_ind; 1480 struct mac_context *mac = cds_get_context(QDF_MODULE_ID_PE); 1481 1482 if (!mac) 1483 return -EINVAL; 1484 1485 if (!mac->sme.ext_scan_ind_cb) { 1486 wma_err("Callback not registered"); 1487 return -EINVAL; 1488 } 1489 param_buf = (WMI_EXTSCAN_TABLE_USAGE_EVENTID_param_tlvs *) 1490 cmd_param_info; 1491 if (!param_buf) { 1492 wma_err("Invalid table usage event"); 1493 return -EINVAL; 1494 } 1495 event = param_buf->fixed_param; 1496 tbl_usg_ind = qdf_mem_malloc(sizeof(*tbl_usg_ind)); 1497 if (!tbl_usg_ind) 1498 return -ENOMEM; 1499 1500 tbl_usg_ind->requestId = event->request_id; 1501 tbl_usg_ind->numResultsAvailable = event->entries_in_use; 1502 mac->sme.ext_scan_ind_cb(mac->hdd_handle, 1503 eSIR_EXTSCAN_SCAN_RES_AVAILABLE_IND, 1504 tbl_usg_ind); 1505 wma_debug("sending scan_res available event to hdd"); 1506 qdf_mem_free(tbl_usg_ind); 1507 return 0; 1508 } 1509 1510 /** 1511 * wma_extscan_capabilities_event_handler() - extscan capabilities event handler 1512 * @handle: wma handle 1513 * @cmd_param_info: event buffer 1514 * @len: length 1515 * 1516 * This function handles capabilities event and indicate 1517 * upper layers with registered callback. 1518 * 1519 * Return: 0 for success or error code. 1520 */ 1521 int wma_extscan_capabilities_event_handler(void *handle, 1522 uint8_t *cmd_param_info, 1523 uint32_t len) 1524 { 1525 WMI_EXTSCAN_CAPABILITIES_EVENTID_param_tlvs *param_buf; 1526 wmi_extscan_capabilities_event_fixed_param *event; 1527 wmi_extscan_cache_capabilities *src_cache; 1528 wmi_extscan_hotlist_monitor_capabilities *src_hotlist; 1529 wmi_extscan_wlan_change_monitor_capabilities *src_change; 1530 struct ext_scan_capabilities_response *dest_capab; 1531 struct mac_context *mac = cds_get_context(QDF_MODULE_ID_PE); 1532 1533 if (!mac) 1534 return -EINVAL; 1535 1536 if (!mac->sme.ext_scan_ind_cb) { 1537 wma_err("Callback not registered"); 1538 return -EINVAL; 1539 } 1540 param_buf = (WMI_EXTSCAN_CAPABILITIES_EVENTID_param_tlvs *) 1541 cmd_param_info; 1542 if (!param_buf) { 1543 wma_err("Invalid capabilities event"); 1544 return -EINVAL; 1545 } 1546 event = param_buf->fixed_param; 1547 src_cache = param_buf->extscan_cache_capabilities; 1548 src_hotlist = param_buf->hotlist_capabilities; 1549 src_change = param_buf->wlan_change_capabilities; 1550 1551 if (!src_cache || !src_hotlist || !src_change) { 1552 wma_err("Invalid capabilities list"); 1553 return -EINVAL; 1554 } 1555 dest_capab = qdf_mem_malloc(sizeof(*dest_capab)); 1556 if (!dest_capab) 1557 return -ENOMEM; 1558 1559 dest_capab->requestId = event->request_id; 1560 dest_capab->max_scan_buckets = src_cache->max_buckets; 1561 dest_capab->max_scan_cache_size = src_cache->scan_cache_entry_size; 1562 dest_capab->max_ap_cache_per_scan = src_cache->max_bssid_per_scan; 1563 dest_capab->max_scan_reporting_threshold = 1564 src_cache->max_table_usage_threshold; 1565 1566 dest_capab->max_hotlist_bssids = src_hotlist->max_hotlist_entries; 1567 dest_capab->max_rssi_sample_size = 1568 src_change->max_rssi_averaging_samples; 1569 dest_capab->max_bssid_history_entries = 1570 src_change->max_rssi_history_entries; 1571 dest_capab->max_significant_wifi_change_aps = 1572 src_change->max_wlan_change_entries; 1573 dest_capab->max_hotlist_ssids = 1574 event->num_extscan_hotlist_ssid; 1575 dest_capab->max_number_epno_networks = 1576 event->num_epno_networks; 1577 dest_capab->max_number_epno_networks_by_ssid = 1578 event->num_epno_networks; 1579 dest_capab->max_number_of_allow_listed_ssid = 1580 event->num_roam_ssid_whitelist; 1581 dest_capab->max_number_of_deny_listed_bssid = 1582 event->num_roam_bssid_blacklist; 1583 dest_capab->status = 0; 1584 1585 wma_debug("request_id: %u status: %d", 1586 dest_capab->requestId, dest_capab->status); 1587 1588 wma_debug("Capabilities: max_scan_buckets: %d, max_hotlist_bssids: %d, max_scan_cache_size: %d, max_ap_cache_per_scan: %d", 1589 dest_capab->max_scan_buckets, 1590 dest_capab->max_hotlist_bssids, dest_capab->max_scan_cache_size, 1591 dest_capab->max_ap_cache_per_scan); 1592 wma_debug("max_scan_reporting_threshold: %d, max_rssi_sample_size: %d, max_bssid_history_entries: %d, max_significant_wifi_change_aps: %d", 1593 dest_capab->max_scan_reporting_threshold, 1594 dest_capab->max_rssi_sample_size, 1595 dest_capab->max_bssid_history_entries, 1596 dest_capab->max_significant_wifi_change_aps); 1597 1598 wma_debug("Capabilities: max_hotlist_ssids: %d, max_number_epno_networks: %d, max_number_epno_networks_by_ssid: %d", 1599 dest_capab->max_hotlist_ssids, 1600 dest_capab->max_number_epno_networks, 1601 dest_capab->max_number_epno_networks_by_ssid); 1602 wma_debug("max_number_of_allow_listed_ssid: %d, max_number_of_deny_listed_bssid: %d", 1603 dest_capab->max_number_of_allow_listed_ssid, 1604 dest_capab->max_number_of_deny_listed_bssid); 1605 1606 mac->sme.ext_scan_ind_cb(mac->hdd_handle, 1607 eSIR_EXTSCAN_GET_CAPABILITIES_IND, dest_capab); 1608 qdf_mem_free(dest_capab); 1609 return 0; 1610 } 1611 1612 /** 1613 * wma_extscan_hotlist_match_event_handler() - hotlist match event handler 1614 * @handle: wma handle 1615 * @cmd_param_info: event buffer 1616 * @len: length 1617 * 1618 * This function handles hotlist match event and indicate 1619 * upper layers with registered callback. 1620 * 1621 * Return: 0 for success or error code. 1622 */ 1623 int wma_extscan_hotlist_match_event_handler(void *handle, 1624 uint8_t *cmd_param_info, 1625 uint32_t len) 1626 { 1627 WMI_EXTSCAN_HOTLIST_MATCH_EVENTID_param_tlvs *param_buf; 1628 wmi_extscan_hotlist_match_event_fixed_param *event; 1629 struct extscan_hotlist_match *dest_hotlist; 1630 tSirWifiScanResult *dest_ap; 1631 wmi_extscan_wlan_descriptor *src_hotlist; 1632 uint32_t numap; 1633 int j, ap_found = 0; 1634 uint32_t buf_len; 1635 struct mac_context *mac = cds_get_context(QDF_MODULE_ID_PE); 1636 1637 if (!mac) 1638 return -EINVAL; 1639 1640 if (!mac->sme.ext_scan_ind_cb) { 1641 wma_err("Callback not registered"); 1642 return -EINVAL; 1643 } 1644 param_buf = (WMI_EXTSCAN_HOTLIST_MATCH_EVENTID_param_tlvs *) 1645 cmd_param_info; 1646 if (!param_buf) { 1647 wma_err("Invalid hotlist match event"); 1648 return -EINVAL; 1649 } 1650 event = param_buf->fixed_param; 1651 src_hotlist = param_buf->hotlist_match; 1652 numap = event->total_entries; 1653 1654 if (!src_hotlist || !numap) { 1655 wma_err("Hotlist AP's list invalid"); 1656 return -EINVAL; 1657 } 1658 if (numap > param_buf->num_hotlist_match) { 1659 wma_err("Invalid no of total enteries %d", numap); 1660 return -EINVAL; 1661 } 1662 if (numap > WMA_EXTSCAN_MAX_HOTLIST_ENTRIES) { 1663 wma_err("Total Entries %u greater than max", numap); 1664 numap = WMA_EXTSCAN_MAX_HOTLIST_ENTRIES; 1665 } 1666 1667 buf_len = sizeof(wmi_extscan_hotlist_match_event_fixed_param) + 1668 WMI_TLV_HDR_SIZE + 1669 (numap * sizeof(wmi_extscan_wlan_descriptor)); 1670 1671 if (buf_len > len) { 1672 wma_err("Invalid buf len from FW %d numap %d", len, numap); 1673 return -EINVAL; 1674 } 1675 1676 dest_hotlist = qdf_mem_malloc(sizeof(*dest_hotlist) + 1677 sizeof(*dest_ap) * numap); 1678 if (!dest_hotlist) 1679 return -ENOMEM; 1680 1681 dest_ap = &dest_hotlist->ap[0]; 1682 dest_hotlist->numOfAps = numap; 1683 dest_hotlist->requestId = event->config_request_id; 1684 1685 if (event->first_entry_index + 1686 event->num_entries_in_page < event->total_entries) 1687 dest_hotlist->moreData = 1; 1688 else 1689 dest_hotlist->moreData = 0; 1690 1691 wma_debug("Hotlist match: requestId: %u numOfAps: %d", 1692 dest_hotlist->requestId, dest_hotlist->numOfAps); 1693 1694 /* 1695 * Currently firmware sends only one bss information in-case 1696 * of both hotlist ap found and lost. 1697 */ 1698 for (j = 0; j < numap; j++) { 1699 dest_ap->rssi = 0; 1700 dest_ap->channel = src_hotlist->channel; 1701 dest_ap->ts = src_hotlist->tstamp; 1702 ap_found = src_hotlist->flags & WMI_HOTLIST_FLAG_PRESENCE; 1703 dest_ap->rtt = src_hotlist->rtt; 1704 dest_ap->rtt_sd = src_hotlist->rtt_sd; 1705 dest_ap->beaconPeriod = src_hotlist->beacon_interval; 1706 dest_ap->capability = src_hotlist->capabilities; 1707 dest_ap->ieLength = src_hotlist->ie_length; 1708 WMI_MAC_ADDR_TO_CHAR_ARRAY(&src_hotlist->bssid, 1709 dest_ap->bssid.bytes); 1710 if (src_hotlist->ssid.ssid_len > WLAN_SSID_MAX_LEN) { 1711 wma_err("Invalid SSID len %d, truncating", 1712 src_hotlist->ssid.ssid_len); 1713 src_hotlist->ssid.ssid_len = WLAN_SSID_MAX_LEN; 1714 } 1715 qdf_mem_copy(dest_ap->ssid, src_hotlist->ssid.ssid, 1716 src_hotlist->ssid.ssid_len); 1717 dest_ap->ssid[src_hotlist->ssid.ssid_len] = '\0'; 1718 dest_ap++; 1719 src_hotlist++; 1720 } 1721 dest_hotlist->ap_found = ap_found; 1722 mac->sme.ext_scan_ind_cb(mac->hdd_handle, 1723 eSIR_EXTSCAN_HOTLIST_MATCH_IND, dest_hotlist); 1724 wma_debug("sending hotlist match event to hdd"); 1725 qdf_mem_free(dest_hotlist); 1726 return 0; 1727 } 1728 1729 /** wma_extscan_find_unique_scan_ids() - find unique scan ids 1730 * @cmd_param_info: event data. 1731 * 1732 * This utility function parses the input bss table of information 1733 * and find the unique number of scan ids 1734 * 1735 * Return: 0 on success; error number otherwise 1736 */ 1737 static int wma_extscan_find_unique_scan_ids(const u_int8_t *cmd_param_info) 1738 { 1739 WMI_EXTSCAN_CACHED_RESULTS_EVENTID_param_tlvs *param_buf; 1740 wmi_extscan_cached_results_event_fixed_param *event; 1741 wmi_extscan_wlan_descriptor *src_hotlist; 1742 wmi_extscan_rssi_info *src_rssi; 1743 int prev_scan_id, scan_ids_cnt, i; 1744 1745 param_buf = (WMI_EXTSCAN_CACHED_RESULTS_EVENTID_param_tlvs *) 1746 cmd_param_info; 1747 event = param_buf->fixed_param; 1748 src_hotlist = param_buf->bssid_list; 1749 src_rssi = param_buf->rssi_list; 1750 1751 /* Find the unique number of scan_id's for grouping */ 1752 prev_scan_id = src_rssi->scan_cycle_id; 1753 scan_ids_cnt = 1; 1754 for (i = 1; i < param_buf->num_rssi_list; i++) { 1755 src_rssi++; 1756 1757 if (prev_scan_id != src_rssi->scan_cycle_id) { 1758 scan_ids_cnt++; 1759 prev_scan_id = src_rssi->scan_cycle_id; 1760 } 1761 } 1762 1763 return scan_ids_cnt; 1764 } 1765 1766 /** wma_fill_num_results_per_scan_id() - fill number of bss per scan id 1767 * @cmd_param_info: event data. 1768 * @scan_id_group: pointer to scan id group. 1769 * 1770 * This utility function parses the input bss table of information 1771 * and finds how many bss are there per unique scan id. 1772 * 1773 * Return: 0 on success; error number otherwise 1774 */ 1775 static int wma_fill_num_results_per_scan_id(const u_int8_t *cmd_param_info, 1776 struct extscan_cached_scan_result *scan_id_group) 1777 { 1778 WMI_EXTSCAN_CACHED_RESULTS_EVENTID_param_tlvs *param_buf; 1779 wmi_extscan_cached_results_event_fixed_param *event; 1780 wmi_extscan_wlan_descriptor *src_hotlist; 1781 wmi_extscan_rssi_info *src_rssi; 1782 struct extscan_cached_scan_result *t_scan_id_grp; 1783 int i, prev_scan_id; 1784 1785 param_buf = (WMI_EXTSCAN_CACHED_RESULTS_EVENTID_param_tlvs *) 1786 cmd_param_info; 1787 event = param_buf->fixed_param; 1788 src_hotlist = param_buf->bssid_list; 1789 src_rssi = param_buf->rssi_list; 1790 t_scan_id_grp = scan_id_group; 1791 1792 prev_scan_id = src_rssi->scan_cycle_id; 1793 1794 t_scan_id_grp->scan_id = src_rssi->scan_cycle_id; 1795 t_scan_id_grp->flags = src_rssi->flags; 1796 t_scan_id_grp->buckets_scanned = src_rssi->buckets_scanned; 1797 t_scan_id_grp->num_results = 1; 1798 for (i = 1; i < param_buf->num_rssi_list; i++) { 1799 src_rssi++; 1800 if (prev_scan_id == src_rssi->scan_cycle_id) { 1801 t_scan_id_grp->num_results++; 1802 } else { 1803 t_scan_id_grp++; 1804 prev_scan_id = t_scan_id_grp->scan_id = 1805 src_rssi->scan_cycle_id; 1806 t_scan_id_grp->flags = src_rssi->flags; 1807 t_scan_id_grp->buckets_scanned = 1808 src_rssi->buckets_scanned; 1809 t_scan_id_grp->num_results = 1; 1810 } 1811 } 1812 return 0; 1813 } 1814 1815 /** wma_group_num_bss_to_scan_id() - group bss to scan id table 1816 * @cmd_param_info: event data. 1817 * @cached_result: pointer to cached table. 1818 * 1819 * This function reads the bss information from the format 1820 * ------------------------------------------------------------------------ 1821 * | bss info {rssi, channel, ssid, bssid, timestamp} | scan id_1 | flags | 1822 * | bss info {rssi, channel, ssid, bssid, timestamp} | scan id_2 | flags | 1823 * ........................................................................ 1824 * | bss info {rssi, channel, ssid, bssid, timestamp} | scan id_N | flags | 1825 * ------------------------------------------------------------------------ 1826 * 1827 * and converts it into the below format and store it 1828 * 1829 * ------------------------------------------------------------------------ 1830 * | scan id_1 | -> bss info_1 -> bss info_2 -> .... bss info_M1 1831 * | scan id_2 | -> bss info_1 -> bss info_2 -> .... bss info_M2 1832 * ...................... 1833 * | scan id_N | -> bss info_1 -> bss info_2 -> .... bss info_Mn 1834 * ------------------------------------------------------------------------ 1835 * 1836 * Return: 0 on success; error number otherwise 1837 */ 1838 static int wma_group_num_bss_to_scan_id(const u_int8_t *cmd_param_info, 1839 struct extscan_cached_scan_results *cached_result) 1840 { 1841 WMI_EXTSCAN_CACHED_RESULTS_EVENTID_param_tlvs *param_buf; 1842 wmi_extscan_cached_results_event_fixed_param *event; 1843 wmi_extscan_wlan_descriptor *src_hotlist; 1844 wmi_extscan_rssi_info *src_rssi; 1845 struct extscan_cached_scan_results *t_cached_result; 1846 struct extscan_cached_scan_result *t_scan_id_grp; 1847 int i, j; 1848 uint32_t total_scan_num_results = 0; 1849 tSirWifiScanResult *ap; 1850 1851 param_buf = (WMI_EXTSCAN_CACHED_RESULTS_EVENTID_param_tlvs *) 1852 cmd_param_info; 1853 event = param_buf->fixed_param; 1854 src_hotlist = param_buf->bssid_list; 1855 src_rssi = param_buf->rssi_list; 1856 t_cached_result = cached_result; 1857 t_scan_id_grp = &t_cached_result->result[0]; 1858 1859 for (i = 0; i < t_cached_result->num_scan_ids; i++) { 1860 total_scan_num_results += t_scan_id_grp->num_results; 1861 t_scan_id_grp++; 1862 } 1863 1864 if (total_scan_num_results > param_buf->num_bssid_list) { 1865 wma_err("total_scan_num_results %d, num_bssid_list %d", 1866 total_scan_num_results, 1867 param_buf->num_bssid_list); 1868 return -EINVAL; 1869 } 1870 1871 t_scan_id_grp = &t_cached_result->result[0]; 1872 wma_debug("num_scan_ids:%d", 1873 t_cached_result->num_scan_ids); 1874 for (i = 0; i < t_cached_result->num_scan_ids; i++) { 1875 wma_debug("num_results:%d", t_scan_id_grp->num_results); 1876 t_scan_id_grp->ap = qdf_mem_malloc(t_scan_id_grp->num_results * 1877 sizeof(*ap)); 1878 if (!t_scan_id_grp->ap) 1879 return -ENOMEM; 1880 1881 ap = &t_scan_id_grp->ap[0]; 1882 for (j = 0; j < t_scan_id_grp->num_results; j++) { 1883 ap->channel = src_hotlist->channel; 1884 ap->ts = WMA_MSEC_TO_USEC(src_rssi->tstamp); 1885 ap->rtt = src_hotlist->rtt; 1886 ap->rtt_sd = src_hotlist->rtt_sd; 1887 ap->beaconPeriod = src_hotlist->beacon_interval; 1888 ap->capability = src_hotlist->capabilities; 1889 ap->ieLength = src_hotlist->ie_length; 1890 1891 /* Firmware already applied noise floor adjustment and 1892 * due to WMI interface "UINT32 rssi", host driver 1893 * receives a positive value, hence convert to 1894 * signed char to get the absolute rssi. 1895 */ 1896 ap->rssi = (signed char) src_rssi->rssi; 1897 WMI_MAC_ADDR_TO_CHAR_ARRAY(&src_hotlist->bssid, 1898 ap->bssid.bytes); 1899 1900 if (src_hotlist->ssid.ssid_len > 1901 WLAN_SSID_MAX_LEN) { 1902 wma_debug("Invalid SSID len %d, truncating", 1903 src_hotlist->ssid.ssid_len); 1904 src_hotlist->ssid.ssid_len = 1905 WLAN_SSID_MAX_LEN; 1906 } 1907 qdf_mem_copy(ap->ssid, src_hotlist->ssid.ssid, 1908 src_hotlist->ssid.ssid_len); 1909 ap->ssid[src_hotlist->ssid.ssid_len] = '\0'; 1910 ap++; 1911 src_rssi++; 1912 src_hotlist++; 1913 } 1914 t_scan_id_grp++; 1915 } 1916 return 0; 1917 } 1918 1919 /** 1920 * wma_extscan_cached_results_event_handler() - cached results event handler 1921 * @handle: wma handle 1922 * @cmd_param_info: event buffer 1923 * @len: length of @cmd_param_info 1924 * 1925 * This function handles cached results event and indicate 1926 * cached results to upper layer. 1927 * 1928 * Return: 0 for success or error code. 1929 */ 1930 int wma_extscan_cached_results_event_handler(void *handle, 1931 uint8_t *cmd_param_info, 1932 uint32_t len) 1933 { 1934 WMI_EXTSCAN_CACHED_RESULTS_EVENTID_param_tlvs *param_buf; 1935 wmi_extscan_cached_results_event_fixed_param *event; 1936 struct extscan_cached_scan_results *dest_cachelist; 1937 struct extscan_cached_scan_result *dest_result; 1938 struct extscan_cached_scan_results empty_cachelist; 1939 wmi_extscan_wlan_descriptor *src_hotlist; 1940 wmi_extscan_rssi_info *src_rssi; 1941 int i, moredata, scan_ids_cnt, buf_len, status; 1942 struct mac_context *mac = cds_get_context(QDF_MODULE_ID_PE); 1943 uint32_t total_len; 1944 bool excess_data = false; 1945 1946 if (!mac) { 1947 wma_err("Invalid mac"); 1948 return -EINVAL; 1949 } 1950 if (!mac->sme.ext_scan_ind_cb) { 1951 wma_err("Callback not registered"); 1952 return -EINVAL; 1953 } 1954 param_buf = (WMI_EXTSCAN_CACHED_RESULTS_EVENTID_param_tlvs *) 1955 cmd_param_info; 1956 if (!param_buf) { 1957 wma_err("Invalid cached results event"); 1958 return -EINVAL; 1959 } 1960 event = param_buf->fixed_param; 1961 src_hotlist = param_buf->bssid_list; 1962 src_rssi = param_buf->rssi_list; 1963 wma_debug("Total_entries: %u first_entry_index: %u num_entries_in_page: %d", 1964 event->total_entries, 1965 event->first_entry_index, 1966 event->num_entries_in_page); 1967 1968 if (!src_hotlist || !src_rssi || !event->num_entries_in_page) { 1969 wma_warn("Cached results empty, send 0 results"); 1970 goto noresults; 1971 } 1972 1973 if (event->num_entries_in_page > 1974 (WMI_SVC_MSG_MAX_SIZE - sizeof(*event))/sizeof(*src_hotlist) || 1975 event->num_entries_in_page > param_buf->num_bssid_list) { 1976 wma_err("excess num_entries_in_page %d in WMI event. num_bssid_list %d", 1977 event->num_entries_in_page, param_buf->num_bssid_list); 1978 return -EINVAL; 1979 } else { 1980 total_len = sizeof(*event) + 1981 (event->num_entries_in_page * sizeof(*src_hotlist)); 1982 } 1983 for (i = 0; i < event->num_entries_in_page; i++) { 1984 if (src_hotlist[i].ie_length > 1985 WMI_SVC_MSG_MAX_SIZE - total_len) { 1986 excess_data = true; 1987 break; 1988 } else { 1989 total_len += src_hotlist[i].ie_length; 1990 wma_debug("total len IE: %d", total_len); 1991 } 1992 1993 if (src_hotlist[i].number_rssi_samples > 1994 (WMI_SVC_MSG_MAX_SIZE - total_len) / sizeof(*src_rssi)) { 1995 excess_data = true; 1996 break; 1997 } else { 1998 total_len += (src_hotlist[i].number_rssi_samples * 1999 sizeof(*src_rssi)); 2000 wma_debug("total len RSSI samples: %d", total_len); 2001 } 2002 } 2003 if (excess_data) { 2004 wma_err("excess data in WMI event"); 2005 return -EINVAL; 2006 } 2007 2008 if (event->first_entry_index + 2009 event->num_entries_in_page < event->total_entries) 2010 moredata = 1; 2011 else 2012 moredata = 0; 2013 2014 dest_cachelist = qdf_mem_malloc(sizeof(*dest_cachelist)); 2015 if (!dest_cachelist) 2016 return -ENOMEM; 2017 2018 qdf_mem_zero(dest_cachelist, sizeof(*dest_cachelist)); 2019 dest_cachelist->request_id = event->request_id; 2020 dest_cachelist->more_data = moredata; 2021 2022 scan_ids_cnt = wma_extscan_find_unique_scan_ids(cmd_param_info); 2023 wma_debug("scan_ids_cnt %d", scan_ids_cnt); 2024 dest_cachelist->num_scan_ids = scan_ids_cnt; 2025 2026 buf_len = sizeof(*dest_result) * scan_ids_cnt; 2027 dest_cachelist->result = qdf_mem_malloc(buf_len); 2028 if (!dest_cachelist->result) { 2029 qdf_mem_free(dest_cachelist); 2030 return -ENOMEM; 2031 } 2032 2033 dest_result = dest_cachelist->result; 2034 wma_fill_num_results_per_scan_id(cmd_param_info, dest_result); 2035 2036 status = wma_group_num_bss_to_scan_id(cmd_param_info, dest_cachelist); 2037 if (!status) 2038 mac->sme.ext_scan_ind_cb(mac->hdd_handle, 2039 eSIR_EXTSCAN_CACHED_RESULTS_IND, 2040 dest_cachelist); 2041 else 2042 wma_debug("wma_group_num_bss_to_scan_id failed, not calling callback"); 2043 2044 dest_result = dest_cachelist->result; 2045 for (i = 0; i < dest_cachelist->num_scan_ids; i++) { 2046 if (dest_result->ap) 2047 qdf_mem_free(dest_result->ap); 2048 dest_result++; 2049 } 2050 qdf_mem_free(dest_cachelist->result); 2051 qdf_mem_free(dest_cachelist); 2052 return status; 2053 2054 noresults: 2055 empty_cachelist.request_id = event->request_id; 2056 empty_cachelist.more_data = 0; 2057 empty_cachelist.num_scan_ids = 0; 2058 2059 mac->sme.ext_scan_ind_cb(mac->hdd_handle, 2060 eSIR_EXTSCAN_CACHED_RESULTS_IND, 2061 &empty_cachelist); 2062 return 0; 2063 } 2064 2065 /** 2066 * wma_extscan_change_results_event_handler() - change results event handler 2067 * @handle: wma handle 2068 * @cmd_param_info: event buffer 2069 * @len: length 2070 * 2071 * This function handles change results event and indicate 2072 * change results to upper layer. 2073 * 2074 * Return: 0 for success or error code. 2075 */ 2076 int wma_extscan_change_results_event_handler(void *handle, 2077 uint8_t *cmd_param_info, 2078 uint32_t len) 2079 { 2080 WMI_EXTSCAN_WLAN_CHANGE_RESULTS_EVENTID_param_tlvs *param_buf; 2081 wmi_extscan_wlan_change_results_event_fixed_param *event; 2082 tSirWifiSignificantChangeEvent *dest_chglist; 2083 tSirWifiSignificantChange *dest_ap; 2084 wmi_extscan_wlan_change_result_bssid *src_chglist; 2085 2086 uint32_t numap; 2087 int i, k; 2088 uint8_t *src_rssi; 2089 int count = 0; 2090 int moredata; 2091 uint32_t rssi_num = 0; 2092 struct mac_context *mac = cds_get_context(QDF_MODULE_ID_PE); 2093 uint32_t buf_len; 2094 bool excess_data = false; 2095 2096 if (!mac) { 2097 wma_err("Invalid mac"); 2098 return -EINVAL; 2099 } 2100 if (!mac->sme.ext_scan_ind_cb) { 2101 wma_err("Callback not registered"); 2102 return -EINVAL; 2103 } 2104 param_buf = (WMI_EXTSCAN_WLAN_CHANGE_RESULTS_EVENTID_param_tlvs *) 2105 cmd_param_info; 2106 if (!param_buf) { 2107 wma_err("Invalid change monitor event"); 2108 return -EINVAL; 2109 } 2110 event = param_buf->fixed_param; 2111 src_chglist = param_buf->bssid_signal_descriptor_list; 2112 src_rssi = param_buf->rssi_list; 2113 numap = event->num_entries_in_page; 2114 2115 if (!src_chglist || !numap) { 2116 wma_err("Results invalid"); 2117 return -EINVAL; 2118 } 2119 if (numap > param_buf->num_bssid_signal_descriptor_list) { 2120 wma_err("Invalid num of entries in page: %d", numap); 2121 return -EINVAL; 2122 } 2123 for (i = 0; i < numap; i++) { 2124 if (src_chglist->num_rssi_samples > (UINT_MAX - rssi_num)) { 2125 wma_err("Invalid num of rssi samples %d numap %d rssi_num %d", 2126 src_chglist->num_rssi_samples, 2127 numap, rssi_num); 2128 return -EINVAL; 2129 } 2130 rssi_num += src_chglist->num_rssi_samples; 2131 src_chglist++; 2132 } 2133 src_chglist = param_buf->bssid_signal_descriptor_list; 2134 2135 if (event->first_entry_index + 2136 event->num_entries_in_page < event->total_entries) { 2137 moredata = 1; 2138 } else { 2139 moredata = 0; 2140 } 2141 2142 do { 2143 if (event->num_entries_in_page > 2144 (WMI_SVC_MSG_MAX_SIZE - sizeof(*event))/ 2145 sizeof(*src_chglist)) { 2146 excess_data = true; 2147 break; 2148 } else { 2149 buf_len = 2150 sizeof(*event) + (event->num_entries_in_page * 2151 sizeof(*src_chglist)); 2152 } 2153 if (rssi_num > 2154 (WMI_SVC_MSG_MAX_SIZE - buf_len)/sizeof(int32_t)) { 2155 excess_data = true; 2156 break; 2157 } 2158 } while (0); 2159 2160 if (excess_data) { 2161 wma_err("buffer len exceeds WMI payload,numap:%d, rssi_num:%d", 2162 numap, rssi_num); 2163 QDF_ASSERT(0); 2164 return -EINVAL; 2165 } 2166 dest_chglist = qdf_mem_malloc(sizeof(*dest_chglist) + 2167 sizeof(*dest_ap) * numap + 2168 sizeof(int32_t) * rssi_num); 2169 if (!dest_chglist) 2170 return -ENOMEM; 2171 2172 dest_ap = &dest_chglist->ap[0]; 2173 for (i = 0; i < numap; i++) { 2174 dest_ap->channel = src_chglist->channel; 2175 WMI_MAC_ADDR_TO_CHAR_ARRAY(&src_chglist->bssid, 2176 dest_ap->bssid.bytes); 2177 dest_ap->numOfRssi = src_chglist->num_rssi_samples; 2178 if (dest_ap->numOfRssi) { 2179 if ((dest_ap->numOfRssi + count) > 2180 param_buf->num_rssi_list) { 2181 wma_err("Invalid num in rssi list: %d", 2182 dest_ap->numOfRssi); 2183 qdf_mem_free(dest_chglist); 2184 return -EINVAL; 2185 } 2186 for (k = 0; k < dest_ap->numOfRssi; k++) { 2187 dest_ap->rssi[k] = WMA_TGT_NOISE_FLOOR_DBM + 2188 src_rssi[count++]; 2189 } 2190 } 2191 dest_ap = (tSirWifiSignificantChange *)((char *)dest_ap + 2192 dest_ap->numOfRssi * sizeof(int32_t) + 2193 sizeof(*dest_ap)); 2194 src_chglist++; 2195 } 2196 dest_chglist->requestId = event->request_id; 2197 dest_chglist->moreData = moredata; 2198 dest_chglist->numResults = numap; 2199 2200 mac->sme.ext_scan_ind_cb(mac->hdd_handle, 2201 eSIR_EXTSCAN_SIGNIFICANT_WIFI_CHANGE_RESULTS_IND, 2202 dest_chglist); 2203 wma_debug("sending change monitor results"); 2204 qdf_mem_free(dest_chglist); 2205 return 0; 2206 } 2207 2208 /** 2209 * wma_passpoint_match_event_handler() - passpoint match found event handler 2210 * @handle: WMA handle 2211 * @cmd_param_info: event data 2212 * @len: event data length 2213 * 2214 * This is the passpoint match found event handler; it reads event data from 2215 * @cmd_param_info and fill in the destination buffer and sends indication 2216 * up layer. 2217 * 2218 * Return: 0 on success; error number otherwise 2219 */ 2220 int wma_passpoint_match_event_handler(void *handle, 2221 uint8_t *cmd_param_info, 2222 uint32_t len) 2223 { 2224 WMI_PASSPOINT_MATCH_EVENTID_param_tlvs *param_buf; 2225 wmi_passpoint_event_hdr *event; 2226 struct wifi_passpoint_match *dest_match; 2227 tSirWifiScanResult *dest_ap; 2228 uint8_t *buf_ptr; 2229 uint32_t buf_len = 0; 2230 bool excess_data = false; 2231 struct mac_context *mac = cds_get_context(QDF_MODULE_ID_PE); 2232 2233 if (!mac) { 2234 wma_err("Invalid mac"); 2235 return -EINVAL; 2236 } 2237 if (!mac->sme.ext_scan_ind_cb) { 2238 wma_err("Callback not registered"); 2239 return -EINVAL; 2240 } 2241 2242 param_buf = (WMI_PASSPOINT_MATCH_EVENTID_param_tlvs *) cmd_param_info; 2243 if (!param_buf) { 2244 wma_err("Invalid passpoint match event"); 2245 return -EINVAL; 2246 } 2247 event = param_buf->fixed_param; 2248 buf_ptr = (uint8_t *)param_buf->fixed_param; 2249 2250 do { 2251 if (event->ie_length > (WMI_SVC_MSG_MAX_SIZE)) { 2252 excess_data = true; 2253 break; 2254 } else { 2255 buf_len = event->ie_length; 2256 } 2257 2258 if (event->anqp_length > (WMI_SVC_MSG_MAX_SIZE)) { 2259 excess_data = true; 2260 break; 2261 } else { 2262 buf_len += event->anqp_length; 2263 } 2264 2265 } while (0); 2266 2267 if (excess_data || buf_len > (WMI_SVC_MSG_MAX_SIZE - sizeof(*event)) || 2268 buf_len > (WMI_SVC_MSG_MAX_SIZE - sizeof(*dest_match)) || 2269 (event->ie_length + event->anqp_length) > param_buf->num_bufp) { 2270 wma_err("IE Length: %u or ANQP Length: %u is huge, num_bufp: %u", 2271 event->ie_length, event->anqp_length, 2272 param_buf->num_bufp); 2273 return -EINVAL; 2274 } 2275 2276 if (event->ssid.ssid_len > WLAN_SSID_MAX_LEN) { 2277 wma_debug("Invalid ssid len %d, truncating", 2278 event->ssid.ssid_len); 2279 event->ssid.ssid_len = WLAN_SSID_MAX_LEN; 2280 } 2281 2282 dest_match = qdf_mem_malloc(sizeof(*dest_match) + buf_len); 2283 if (!dest_match) 2284 return -EINVAL; 2285 2286 dest_ap = &dest_match->ap; 2287 dest_match->request_id = 0; 2288 dest_match->id = event->id; 2289 dest_match->anqp_len = event->anqp_length; 2290 wma_info("passpoint match: id: %u anqp length %u", 2291 dest_match->id, dest_match->anqp_len); 2292 2293 dest_ap->channel = event->channel_mhz; 2294 dest_ap->ts = event->timestamp; 2295 dest_ap->rtt = event->rtt; 2296 dest_ap->rssi = event->rssi; 2297 dest_ap->rtt_sd = event->rtt_sd; 2298 dest_ap->beaconPeriod = event->beacon_period; 2299 dest_ap->capability = event->capability; 2300 dest_ap->ieLength = event->ie_length; 2301 WMI_MAC_ADDR_TO_CHAR_ARRAY(&event->bssid, dest_ap->bssid.bytes); 2302 qdf_mem_copy(dest_ap->ssid, event->ssid.ssid, 2303 event->ssid.ssid_len); 2304 dest_ap->ssid[event->ssid.ssid_len] = '\0'; 2305 qdf_mem_copy(dest_ap->ieData, buf_ptr + sizeof(*event) + 2306 WMI_TLV_HDR_SIZE, dest_ap->ieLength); 2307 qdf_mem_copy(dest_match->anqp, buf_ptr + sizeof(*event) + 2308 WMI_TLV_HDR_SIZE + dest_ap->ieLength, 2309 dest_match->anqp_len); 2310 2311 mac->sme.ext_scan_ind_cb(mac->hdd_handle, 2312 eSIR_PASSPOINT_NETWORK_FOUND_IND, 2313 dest_match); 2314 wma_debug("sending passpoint match event to hdd"); 2315 qdf_mem_free(dest_match); 2316 return 0; 2317 } 2318 2319 QDF_STATUS wma_start_extscan(tp_wma_handle wma, 2320 struct wifi_scan_cmd_req_params *params) 2321 { 2322 QDF_STATUS status; 2323 struct wmi_unified *wmi_handle; 2324 2325 if (wma_validate_handle(wma)) 2326 return QDF_STATUS_E_INVAL; 2327 2328 wmi_handle = wma->wmi_handle; 2329 if (wmi_validate_handle(wmi_handle)) 2330 return QDF_STATUS_E_INVAL; 2331 2332 if (!wmi_service_enabled(wmi_handle, wmi_service_extscan)) { 2333 wma_err("extscan not enabled"); 2334 return QDF_STATUS_E_FAILURE; 2335 } 2336 2337 if (!params) { 2338 wma_err("NULL param"); 2339 return QDF_STATUS_E_NOMEM; 2340 } 2341 2342 status = wmi_unified_start_extscan_cmd(wmi_handle, params); 2343 if (QDF_IS_STATUS_SUCCESS(status)) 2344 wma->interfaces[params->vdev_id].extscan_in_progress = true; 2345 2346 wma_debug("Exit, vdev %d, status %d", params->vdev_id, status); 2347 2348 return status; 2349 } 2350 2351 QDF_STATUS wma_stop_extscan(tp_wma_handle wma, 2352 struct extscan_stop_req_params *params) 2353 { 2354 QDF_STATUS status; 2355 struct wmi_unified *wmi_handle; 2356 2357 if (wma_validate_handle(wma)) 2358 return QDF_STATUS_E_INVAL; 2359 2360 wmi_handle = wma->wmi_handle; 2361 if (wmi_validate_handle(wmi_handle)) 2362 return QDF_STATUS_E_INVAL; 2363 2364 if (!wmi_service_enabled(wmi_handle, wmi_service_extscan)) { 2365 wma_err("extscan not enabled"); 2366 return QDF_STATUS_E_FAILURE; 2367 } 2368 2369 status = wmi_unified_stop_extscan_cmd(wmi_handle, params); 2370 if (QDF_IS_STATUS_ERROR(status)) 2371 return status; 2372 2373 wma->interfaces[params->vdev_id].extscan_in_progress = false; 2374 wma_debug("Extscan stop request sent successfully for vdev %d", 2375 params->vdev_id); 2376 2377 return status; 2378 } 2379 2380 QDF_STATUS wma_extscan_start_hotlist_monitor(tp_wma_handle wma, 2381 struct extscan_bssid_hotlist_set_params *params) 2382 { 2383 struct wmi_unified *wmi_handle; 2384 2385 if (wma_validate_handle(wma)) 2386 return QDF_STATUS_E_INVAL; 2387 2388 wmi_handle = wma->wmi_handle; 2389 if (wmi_validate_handle(wmi_handle)) 2390 return QDF_STATUS_E_INVAL; 2391 2392 if (!params) { 2393 wma_err("Invalid params"); 2394 return QDF_STATUS_E_INVAL; 2395 } 2396 2397 return wmi_unified_extscan_start_hotlist_monitor_cmd(wmi_handle, 2398 params); 2399 } 2400 2401 QDF_STATUS wma_extscan_stop_hotlist_monitor(tp_wma_handle wma, 2402 struct extscan_bssid_hotlist_reset_params *params) 2403 { 2404 struct wmi_unified *wmi_handle; 2405 2406 if (wma_validate_handle(wma)) 2407 return QDF_STATUS_E_INVAL; 2408 2409 wmi_handle = wma->wmi_handle; 2410 if (wmi_validate_handle(wmi_handle)) 2411 return QDF_STATUS_E_INVAL; 2412 2413 if (!params) { 2414 wma_err("Invalid params"); 2415 return QDF_STATUS_E_INVAL; 2416 } 2417 if (!wmi_service_enabled(wmi_handle, wmi_service_extscan)) { 2418 wma_err("extscan not enabled"); 2419 return QDF_STATUS_E_FAILURE; 2420 } 2421 2422 return wmi_unified_extscan_stop_hotlist_monitor_cmd(wmi_handle, 2423 params); 2424 } 2425 2426 QDF_STATUS 2427 wma_extscan_start_change_monitor(tp_wma_handle wma, 2428 struct extscan_set_sig_changereq_params *params) 2429 { 2430 QDF_STATUS status; 2431 struct wmi_unified *wmi_handle; 2432 2433 if (wma_validate_handle(wma)) 2434 return QDF_STATUS_E_INVAL; 2435 2436 wmi_handle = wma->wmi_handle; 2437 if (wmi_validate_handle(wmi_handle)) 2438 return QDF_STATUS_E_INVAL; 2439 2440 if (!params) { 2441 wma_err("NULL params"); 2442 return QDF_STATUS_E_NOMEM; 2443 } 2444 2445 status = wmi_unified_extscan_start_change_monitor_cmd(wmi_handle, 2446 params); 2447 return status; 2448 } 2449 2450 QDF_STATUS wma_extscan_stop_change_monitor(tp_wma_handle wma, 2451 struct extscan_capabilities_reset_params *params) 2452 { 2453 struct wmi_unified *wmi_handle; 2454 2455 if (wma_validate_handle(wma)) 2456 return QDF_STATUS_E_INVAL; 2457 2458 wmi_handle = wma->wmi_handle; 2459 if (wmi_validate_handle(wmi_handle)) 2460 return QDF_STATUS_E_INVAL; 2461 2462 if (!wmi_service_enabled(wmi_handle, wmi_service_extscan)) { 2463 wma_err("ext scan not enabled"); 2464 return QDF_STATUS_E_FAILURE; 2465 } 2466 2467 return wmi_unified_extscan_stop_change_monitor_cmd(wmi_handle, 2468 params); 2469 } 2470 2471 QDF_STATUS 2472 wma_extscan_get_cached_results(tp_wma_handle wma, 2473 struct extscan_cached_result_params *params) 2474 { 2475 struct wmi_unified *wmi_handle; 2476 2477 if (wma_validate_handle(wma)) 2478 return QDF_STATUS_E_INVAL; 2479 2480 wmi_handle = wma->wmi_handle; 2481 if (wmi_validate_handle(wmi_handle)) 2482 return QDF_STATUS_E_INVAL; 2483 2484 if (!wmi_service_enabled(wmi_handle, wmi_service_extscan)) { 2485 wma_err("extscan not enabled"); 2486 return QDF_STATUS_E_FAILURE; 2487 } 2488 2489 return wmi_unified_extscan_get_cached_results_cmd(wmi_handle, 2490 params); 2491 } 2492 2493 QDF_STATUS 2494 wma_extscan_get_capabilities(tp_wma_handle wma, 2495 struct extscan_capabilities_params *params) 2496 { 2497 struct wmi_unified *wmi_handle; 2498 2499 if (wma_validate_handle(wma)) 2500 return QDF_STATUS_E_INVAL; 2501 2502 wmi_handle = wma->wmi_handle; 2503 if (wmi_validate_handle(wmi_handle)) 2504 return QDF_STATUS_E_INVAL; 2505 2506 if (!wmi_service_enabled(wmi_handle, wmi_service_extscan)) { 2507 wma_err("extscan not enabled"); 2508 return QDF_STATUS_E_FAILURE; 2509 } 2510 2511 return wmi_unified_extscan_get_capabilities_cmd(wmi_handle, 2512 params); 2513 } 2514 2515 QDF_STATUS wma_set_epno_network_list(tp_wma_handle wma, 2516 struct wifi_enhanced_pno_params *req) 2517 { 2518 QDF_STATUS status; 2519 struct wmi_unified *wmi_handle; 2520 2521 wma_debug("Enter"); 2522 2523 if (wma_validate_handle(wma)) 2524 return QDF_STATUS_E_FAILURE; 2525 2526 wmi_handle = wma->wmi_handle; 2527 if (wmi_validate_handle(wmi_handle)) 2528 return QDF_STATUS_E_FAILURE; 2529 2530 if (!wmi_service_enabled(wmi_handle, wmi_service_extscan)) { 2531 wma_err("extscan not enabled"); 2532 return QDF_STATUS_E_NOSUPPORT; 2533 } 2534 2535 status = wmi_unified_set_epno_network_list_cmd(wmi_handle, req); 2536 wma_debug("Exit, vdev %d, status %d", req->vdev_id, status); 2537 2538 return status; 2539 } 2540 2541 QDF_STATUS 2542 wma_set_passpoint_network_list(tp_wma_handle wma, 2543 struct wifi_passpoint_req_param *params) 2544 { 2545 QDF_STATUS status; 2546 struct wmi_unified *wmi_handle; 2547 2548 wma_debug("Enter"); 2549 2550 if (wma_validate_handle(wma)) 2551 return QDF_STATUS_E_FAILURE; 2552 2553 wmi_handle = wma->wmi_handle; 2554 if (wmi_validate_handle(wmi_handle)) 2555 return QDF_STATUS_E_FAILURE; 2556 2557 if (!wmi_service_enabled(wmi_handle, wmi_service_extscan)) { 2558 wma_err("extscan not enabled"); 2559 return QDF_STATUS_E_NOSUPPORT; 2560 } 2561 2562 status = wmi_unified_set_passpoint_network_list_cmd(wmi_handle, 2563 params); 2564 wma_debug("Exit, vdev %d, status %d", params->vdev_id, status); 2565 2566 return status; 2567 } 2568 2569 QDF_STATUS 2570 wma_reset_passpoint_network_list(tp_wma_handle wma, 2571 struct wifi_passpoint_req_param *params) 2572 { 2573 QDF_STATUS status; 2574 struct wmi_unified *wmi_handle; 2575 2576 wma_debug("Enter"); 2577 2578 if (wma_validate_handle(wma)) 2579 return QDF_STATUS_E_FAILURE; 2580 2581 wmi_handle = wma->wmi_handle; 2582 if (wmi_validate_handle(wmi_handle)) 2583 return QDF_STATUS_E_FAILURE; 2584 2585 if (!wmi_service_enabled(wmi_handle, wmi_service_extscan)) { 2586 wma_err("extscan not enabled"); 2587 return QDF_STATUS_E_NOSUPPORT; 2588 } 2589 2590 status = wmi_unified_reset_passpoint_network_list_cmd(wmi_handle, 2591 params); 2592 wma_debug("Exit, vdev %d, status %d", params->vdev_id, status); 2593 2594 return status; 2595 } 2596 2597 #endif 2598 2599 QDF_STATUS wma_scan_probe_setoui(tp_wma_handle wma, 2600 struct scan_mac_oui *set_oui) 2601 { 2602 struct wmi_unified *wmi_handle; 2603 2604 if (wma_validate_handle(wma)) 2605 return QDF_STATUS_E_INVAL; 2606 2607 wmi_handle = wma->wmi_handle; 2608 if (wmi_validate_handle(wmi_handle)) 2609 return QDF_STATUS_E_INVAL; 2610 2611 if (!wma_is_vdev_valid(set_oui->vdev_id)) { 2612 wma_err("vdev_id: %d is not active", set_oui->vdev_id); 2613 return QDF_STATUS_E_INVAL; 2614 } 2615 2616 return wmi_unified_scan_probe_setoui_cmd(wmi_handle, set_oui); 2617 } 2618 2619 /** 2620 * wma_roam_better_ap_handler() - better ap event handler 2621 * @wma: wma handle 2622 * @vdev_id: vdev id 2623 * 2624 * Handler for WMI_ROAM_REASON_BETTER_AP event from roam firmware in Rome. 2625 * This event means roam algorithm in Rome has found a better matching 2626 * candidate AP. The indication is sent to SME. 2627 * 2628 * Return: none 2629 */ 2630 void wma_roam_better_ap_handler(tp_wma_handle wma, uint32_t vdev_id) 2631 { 2632 struct scheduler_msg msg = {0}; 2633 QDF_STATUS status; 2634 struct cm_host_roam_start_ind *ind; 2635 2636 ind = qdf_mem_malloc(sizeof(*ind)); 2637 if (!ind) 2638 return; 2639 2640 ind->pdev = wma->pdev; 2641 ind->vdev_id = vdev_id; 2642 msg.bodyptr = ind; 2643 msg.callback = wlan_cm_host_roam_start; 2644 wma_debug("Posting ROam start ind to connection manager, vdev %d", 2645 vdev_id); 2646 status = scheduler_post_message(QDF_MODULE_ID_WMA, 2647 QDF_MODULE_ID_OS_IF, 2648 QDF_MODULE_ID_SCAN, &msg); 2649 2650 if (QDF_IS_STATUS_ERROR(status)) 2651 qdf_mem_free(msg.bodyptr); 2652 } 2653 2654 #ifdef WLAN_FEATURE_ROAM_OFFLOAD 2655 /** 2656 * wma_invalid_roam_reason_handler() - Handle Invalid roam notification 2657 * @wma: wma handle 2658 * @vdev_id: vdev id 2659 * @op_code: Operation to be done by the callback 2660 * 2661 * This function calls pe and csr callbacks with proper op_code 2662 * 2663 * Return: None 2664 */ 2665 static void wma_invalid_roam_reason_handler(tp_wma_handle wma_handle, 2666 uint32_t vdev_id, 2667 enum cm_roam_notif notif) 2668 { 2669 struct roam_offload_synch_ind *roam_synch_data; 2670 enum sir_roam_op_code op_code; 2671 2672 if (notif == CM_ROAM_NOTIF_ROAM_START) { 2673 op_code = SIR_ROAMING_START; 2674 } else if (notif == CM_ROAM_NOTIF_ROAM_ABORT) { 2675 op_code = SIR_ROAMING_ABORT; 2676 lim_sae_auth_cleanup_retry(wma_handle->mac_context, vdev_id); 2677 } else { 2678 wma_debug("Invalid notif %d", notif); 2679 return; 2680 } 2681 roam_synch_data = qdf_mem_malloc(sizeof(*roam_synch_data)); 2682 if (!roam_synch_data) 2683 return; 2684 2685 roam_synch_data->roamed_vdev_id = vdev_id; 2686 if (notif != CM_ROAM_NOTIF_ROAM_START) 2687 wma_handle->pe_roam_synch_cb(wma_handle->mac_context, 2688 roam_synch_data->roamed_vdev_id, 2689 roam_synch_data, 0, op_code); 2690 2691 if (notif == CM_ROAM_NOTIF_ROAM_START) 2692 cm_fw_roam_start_req(wma_handle->psoc, vdev_id); 2693 else 2694 cm_fw_roam_abort_req(wma_handle->psoc, vdev_id); 2695 2696 qdf_mem_free(roam_synch_data); 2697 } 2698 2699 void wma_handle_roam_sync_timeout(tp_wma_handle wma_handle, 2700 struct roam_sync_timeout_timer_info *info) 2701 { 2702 wma_invalid_roam_reason_handler(wma_handle, info->vdev_id, 2703 CM_ROAM_NOTIF_ROAM_ABORT); 2704 } 2705 2706 void cm_invalid_roam_reason_handler(uint32_t vdev_id, enum cm_roam_notif notif, 2707 uint32_t reason) 2708 { 2709 tp_wma_handle wma_handle = cds_get_context(QDF_MODULE_ID_WMA); 2710 2711 if (!wma_handle) { 2712 QDF_ASSERT(0); 2713 return; 2714 } 2715 wma_invalid_roam_reason_handler(wma_handle, vdev_id, notif); 2716 2717 if (notif == CM_ROAM_NOTIF_SCAN_START || 2718 notif == CM_ROAM_NOTIF_SCAN_END) 2719 cm_report_roam_rt_stats(wma_handle->psoc, vdev_id, 2720 ROAM_RT_STATS_TYPE_SCAN_STATE, 2721 NULL, notif, 0, reason); 2722 } 2723 #endif 2724 2725 static void 2726 wma_handle_roam_reason_invoke_roam_fail(tp_wma_handle wma_handle, 2727 uint8_t vdev_id, uint32_t notif_params) 2728 { 2729 struct roam_offload_synch_ind *roam_synch_data; 2730 2731 roam_synch_data = qdf_mem_malloc(sizeof(*roam_synch_data)); 2732 if (!roam_synch_data) 2733 return; 2734 2735 lim_sae_auth_cleanup_retry(wma_handle->mac_context, vdev_id); 2736 roam_synch_data->roamed_vdev_id = vdev_id; 2737 cm_fw_roam_invoke_fail(wma_handle->psoc, vdev_id); 2738 wlan_cm_update_roam_states(wma_handle->psoc, vdev_id, 2739 notif_params, 2740 ROAM_INVOKE_FAIL_REASON); 2741 qdf_mem_free(roam_synch_data); 2742 } 2743 2744 static void wma_handle_roam_reason_btm(uint8_t vdev_id) 2745 { 2746 tp_wma_handle wma_handle = cds_get_context(QDF_MODULE_ID_WMA); 2747 2748 if (!wma_handle) { 2749 QDF_ASSERT(0); 2750 return; 2751 } 2752 /* 2753 * This event is received from firmware if firmware is unable to 2754 * find candidate AP after roam scan and BTM request from AP 2755 * has disassoc imminent bit set. 2756 */ 2757 wma_debug("Kickout due to btm request"); 2758 wma_sta_kickout_event(HOST_STA_KICKOUT_REASON_BTM, vdev_id, NULL); 2759 wma_handle_disconnect_reason(wma_handle, vdev_id, 2760 HAL_DEL_STA_REASON_CODE_BTM_DISASSOC_IMMINENT); 2761 } 2762 2763 static void wma_handle_roam_reason_bmiss(uint8_t vdev_id, uint32_t rssi) 2764 { 2765 tp_wma_handle wma_handle = cds_get_context(QDF_MODULE_ID_WMA); 2766 2767 if (!wma_handle) { 2768 QDF_ASSERT(0); 2769 return; 2770 } 2771 /* 2772 * WMI_ROAM_REASON_BMISS can get called in soft IRQ context, so 2773 * avoid using CSR/PE structure directly 2774 */ 2775 wma_debug("Beacon Miss for vdevid %x", vdev_id); 2776 mlme_set_hb_ap_rssi(wma_handle->interfaces[vdev_id].vdev, rssi); 2777 wma_beacon_miss_handler(wma_handle, vdev_id, rssi); 2778 wma_sta_kickout_event(HOST_STA_KICKOUT_REASON_BMISS, vdev_id, NULL); 2779 } 2780 2781 static void wma_handle_roam_reason_better_ap(uint8_t vdev_id, uint32_t rssi) 2782 { 2783 tp_wma_handle wma_handle = cds_get_context(QDF_MODULE_ID_WMA); 2784 2785 if (!wma_handle) { 2786 QDF_ASSERT(0); 2787 return; 2788 } 2789 /* 2790 * WMI_ROAM_REASON_BETTER_AP can get called in soft IRQ context, 2791 * so avoid using CSR/PE structure directly. 2792 */ 2793 wma_debug("Better AP found for vdevid %x, rssi %d", vdev_id, rssi); 2794 mlme_set_roam_reason_better_ap(wma_handle->interfaces[vdev_id].vdev, 2795 false); 2796 wma_roam_better_ap_handler(wma_handle, vdev_id); 2797 } 2798 2799 static void wma_handle_roam_reason_suitable_ap(uint8_t vdev_id, uint32_t rssi) 2800 { 2801 tp_wma_handle wma_handle = cds_get_context(QDF_MODULE_ID_WMA); 2802 2803 if (!wma_handle) { 2804 QDF_ASSERT(0); 2805 return; 2806 } 2807 /* 2808 * WMI_ROAM_REASON_SUITABLE_AP can get called in soft IRQ 2809 * context, so avoid using CSR/PE structure directly. 2810 */ 2811 mlme_set_roam_reason_better_ap(wma_handle->interfaces[vdev_id].vdev, 2812 true); 2813 mlme_set_hb_ap_rssi(wma_handle->interfaces[vdev_id].vdev, rssi); 2814 wma_debug("Bmiss scan AP found for vdevid %x, rssi %d", vdev_id, rssi); 2815 wma_roam_better_ap_handler(wma_handle, vdev_id); 2816 } 2817 2818 static void 2819 wma_update_pdev_hw_mode_trans_ind(tp_wma_handle wma, 2820 struct cm_hw_mode_trans_ind *trans_ind) 2821 { 2822 uint32_t i; 2823 2824 /* Store the vdev-mac map in WMA and send to policy manager */ 2825 for (i = 0; i < trans_ind->num_vdev_mac_entries; i++) 2826 wma_update_intf_hw_mode_params( 2827 trans_ind->vdev_mac_map[i].vdev_id, 2828 trans_ind->vdev_mac_map[i].mac_id, 2829 trans_ind->new_hw_mode_index); 2830 2831 wma->old_hw_mode_index = trans_ind->old_hw_mode_index; 2832 wma->new_hw_mode_index = trans_ind->new_hw_mode_index; 2833 policy_mgr_update_new_hw_mode_index(wma->psoc, 2834 trans_ind->new_hw_mode_index); 2835 policy_mgr_update_old_hw_mode_index(wma->psoc, 2836 trans_ind->old_hw_mode_index); 2837 2838 wma_debug("Updated: old_hw_mode_index:%d new_hw_mode_index:%d", 2839 wma->old_hw_mode_index, wma->new_hw_mode_index); 2840 } 2841 2842 static void 2843 wma_handle_hw_mode_trans_ind(tp_wma_handle wma_handle, 2844 struct cm_hw_mode_trans_ind *hw_mode_trans_ind) 2845 { 2846 struct scheduler_msg sme_msg = {0}; 2847 QDF_STATUS status; 2848 2849 if (hw_mode_trans_ind) { 2850 wma_update_pdev_hw_mode_trans_ind(wma_handle, 2851 hw_mode_trans_ind); 2852 wma_debug("Update HW mode"); 2853 sme_msg.type = eWNI_SME_HW_MODE_TRANS_IND; 2854 sme_msg.bodyptr = hw_mode_trans_ind; 2855 2856 status = scheduler_post_message(QDF_MODULE_ID_WMA, 2857 QDF_MODULE_ID_SME, 2858 QDF_MODULE_ID_SME, &sme_msg); 2859 if (QDF_IS_STATUS_ERROR(status)) 2860 qdf_mem_free(hw_mode_trans_ind); 2861 } else { 2862 wma_debug("hw_mode transition fixed param is NULL"); 2863 } 2864 } 2865 2866 int cm_rso_cmd_status_event_handler(uint8_t vdev_id, enum cm_roam_notif notif) 2867 { 2868 return wma_rso_cmd_status_event_handler(vdev_id, notif); 2869 } 2870 2871 void 2872 cm_handle_roam_reason_invoke_roam_fail(uint8_t vdev_id, uint32_t notif_params, 2873 struct cm_hw_mode_trans_ind *trans_ind) 2874 { 2875 tp_wma_handle wma_handle = cds_get_context(QDF_MODULE_ID_WMA); 2876 2877 if (!wma_handle) { 2878 QDF_ASSERT(0); 2879 return; 2880 } 2881 wma_handle_hw_mode_trans_ind(wma_handle, trans_ind); 2882 wma_handle_roam_reason_invoke_roam_fail(wma_handle, vdev_id, 2883 notif_params); 2884 cm_report_roam_rt_stats(wma_handle->psoc, vdev_id, 2885 ROAM_RT_STATS_TYPE_INVOKE_FAIL_REASON, 2886 NULL, notif_params, 0, 0); 2887 } 2888 2889 void 2890 cm_handle_roam_sync_update_hw_mode(struct cm_hw_mode_trans_ind *trans_ind) 2891 { 2892 tp_wma_handle wma_handle = cds_get_context(QDF_MODULE_ID_WMA); 2893 struct cm_hw_mode_trans_ind *trans_ind_data; 2894 2895 if (!wma_handle) { 2896 wma_err("invalid wma handle"); 2897 return; 2898 } 2899 trans_ind_data = qdf_mem_malloc(sizeof(*trans_ind_data)); 2900 if (!trans_ind_data) 2901 return; 2902 qdf_mem_copy(trans_ind_data, trans_ind, sizeof(*trans_ind_data)); 2903 wma_handle_hw_mode_trans_ind(wma_handle, trans_ind_data); 2904 } 2905 2906 static void 2907 wma_handle_roam_reason_deauth(uint8_t vdev_id, uint32_t notif_params, 2908 uint32_t notif_params1, 2909 uint8_t *deauth_disassoc_frame) 2910 { 2911 tp_wma_handle wma_handle = cds_get_context(QDF_MODULE_ID_WMA); 2912 struct roam_offload_synch_ind *roam_synch_data; 2913 2914 if (!wma_handle) { 2915 QDF_ASSERT(0); 2916 return; 2917 } 2918 wma_debug("Received disconnect roam event reason:%d", notif_params); 2919 wma_handle->pe_disconnect_cb(wma_handle->mac_context, 2920 vdev_id, 2921 deauth_disassoc_frame, notif_params1, 2922 notif_params); 2923 roam_synch_data = qdf_mem_malloc(sizeof(*roam_synch_data)); 2924 if (!roam_synch_data) 2925 return; 2926 2927 roam_synch_data->roamed_vdev_id = vdev_id; 2928 qdf_mem_free(roam_synch_data); 2929 } 2930 2931 void cm_handle_roam_reason_deauth(uint8_t vdev_id, uint32_t notif_params, 2932 uint8_t *deauth_disassoc_frame, 2933 uint32_t frame_len) 2934 { 2935 wma_handle_roam_reason_deauth(vdev_id, notif_params, frame_len, 2936 deauth_disassoc_frame); 2937 } 2938 2939 void cm_handle_roam_reason_btm(uint8_t vdev_id) 2940 { 2941 wma_handle_roam_reason_btm(vdev_id); 2942 } 2943 2944 void cm_handle_roam_reason_bmiss(uint8_t vdev_id, uint32_t rssi) 2945 { 2946 wma_handle_roam_reason_bmiss(vdev_id, rssi); 2947 } 2948 2949 void cm_handle_roam_reason_better_ap(uint8_t vdev_id, uint32_t rssi) 2950 { 2951 wma_handle_roam_reason_better_ap(vdev_id, rssi); 2952 } 2953 2954 void cm_handle_roam_reason_suitable_ap(uint8_t vdev_id, uint32_t rssi) 2955 { 2956 wma_handle_roam_reason_suitable_ap(vdev_id, rssi); 2957 } 2958 2959 #ifdef WLAN_FEATURE_ROAM_OFFLOAD 2960 static void 2961 wma_handle_roam_reason_ho_failed(uint8_t vdev_id, struct qdf_mac_addr bssid, 2962 struct cm_hw_mode_trans_ind *hw_mode_trans_ind) 2963 { 2964 tp_wma_handle wma_handle = cds_get_context(QDF_MODULE_ID_WMA); 2965 2966 if (!wma_handle) { 2967 QDF_ASSERT(0); 2968 return; 2969 } 2970 /* 2971 * WMI_ROAM_REASON_HO_FAILED can get called in soft IRQ context, 2972 * so avoid using CSR/PE structure directly. 2973 */ 2974 wma_err("LFR3:Hand-Off Failed for vdevid %x", vdev_id); 2975 wma_debug("mac addr to avoid " QDF_MAC_ADDR_FMT, 2976 QDF_MAC_ADDR_REF(bssid.bytes)); 2977 wma_handle_hw_mode_trans_ind(wma_handle, hw_mode_trans_ind); 2978 cm_fw_ho_fail_req(wma_handle->psoc, vdev_id, bssid); 2979 lim_sae_auth_cleanup_retry(wma_handle->mac_context, vdev_id); 2980 } 2981 2982 void 2983 cm_handle_roam_reason_ho_failed(uint8_t vdev_id, struct qdf_mac_addr bssid, 2984 struct cm_hw_mode_trans_ind *hw_mode_trans_ind) 2985 { 2986 wma_handle_roam_reason_ho_failed(vdev_id, bssid, hw_mode_trans_ind); 2987 } 2988 #endif 2989 2990 #ifdef FEATURE_LFR_SUBNET_DETECTION 2991 QDF_STATUS wma_set_gateway_params(tp_wma_handle wma, 2992 struct gateway_update_req_param *req) 2993 { 2994 if (wma_validate_handle(wma)) 2995 return QDF_STATUS_E_INVAL; 2996 2997 return wmi_unified_set_gateway_params_cmd(wma->wmi_handle, req); 2998 } 2999 #endif /* FEATURE_LFR_SUBNET_DETECTION */ 3000 3001 /** 3002 * wma_ht40_stop_obss_scan() - ht40 obss stop scan 3003 * @wma: WMA handle 3004 * @vdev_id: vdev identifier 3005 * 3006 * Return: Return QDF_STATUS, otherwise appropriate failure code 3007 */ 3008 QDF_STATUS wma_ht40_stop_obss_scan(tp_wma_handle wma, int32_t vdev_id) 3009 { 3010 QDF_STATUS status; 3011 wmi_buf_t buf; 3012 wmi_obss_scan_disable_cmd_fixed_param *cmd; 3013 int len = sizeof(*cmd); 3014 3015 buf = wmi_buf_alloc(wma->wmi_handle, len); 3016 if (!buf) 3017 return QDF_STATUS_E_NOMEM; 3018 3019 wma_debug("cmd %x vdev_id %d", WMI_OBSS_SCAN_DISABLE_CMDID, vdev_id); 3020 3021 cmd = (wmi_obss_scan_disable_cmd_fixed_param *) wmi_buf_data(buf); 3022 WMITLV_SET_HDR(&cmd->tlv_header, 3023 WMITLV_TAG_STRUC_wmi_obss_scan_disable_cmd_fixed_param, 3024 WMITLV_GET_STRUCT_TLVLEN( 3025 wmi_obss_scan_disable_cmd_fixed_param)); 3026 3027 cmd->vdev_id = vdev_id; 3028 status = wmi_unified_cmd_send(wma->wmi_handle, buf, len, 3029 WMI_OBSS_SCAN_DISABLE_CMDID); 3030 if (QDF_IS_STATUS_ERROR(status)) 3031 wmi_buf_free(buf); 3032 3033 return status; 3034 } 3035 3036 /** 3037 * wma_send_ht40_obss_scanind() - ht40 obss start scan indication 3038 * @wma: WMA handle 3039 * @req: start scan request 3040 * 3041 * Return: Return QDF_STATUS, otherwise appropriate failure code 3042 */ 3043 QDF_STATUS wma_send_ht40_obss_scanind(tp_wma_handle wma, 3044 struct obss_ht40_scanind *req) 3045 { 3046 QDF_STATUS status; 3047 wmi_buf_t buf; 3048 wmi_obss_scan_enable_cmd_fixed_param *cmd; 3049 int len = 0; 3050 uint8_t *buf_ptr, i; 3051 uint8_t *channel_list; 3052 uint32_t *chan_freq_list; 3053 3054 len += sizeof(wmi_obss_scan_enable_cmd_fixed_param); 3055 3056 len += WMI_TLV_HDR_SIZE; 3057 len += qdf_roundup(sizeof(uint8_t) * req->channel_count, 3058 sizeof(uint32_t)); 3059 3060 len += WMI_TLV_HDR_SIZE; 3061 len += qdf_roundup(sizeof(uint8_t) * 1, sizeof(uint32_t)); 3062 3063 /* length calculation for chan_freqs */ 3064 len += WMI_TLV_HDR_SIZE; 3065 len += sizeof(uint32_t) * req->channel_count; 3066 3067 wma_debug("cmdlen %d vdev_id %d channel count %d iefield_len %d", 3068 len, req->bss_id, req->channel_count, req->iefield_len); 3069 3070 wma_debug("scantype %d active_time %d passive %d Obss interval %d", 3071 req->scan_type, req->obss_active_dwelltime, 3072 req->obss_passive_dwelltime, 3073 req->obss_width_trigger_interval); 3074 3075 buf = wmi_buf_alloc(wma->wmi_handle, len); 3076 if (!buf) 3077 return QDF_STATUS_E_NOMEM; 3078 3079 cmd = (wmi_obss_scan_enable_cmd_fixed_param *) wmi_buf_data(buf); 3080 WMITLV_SET_HDR(&cmd->tlv_header, 3081 WMITLV_TAG_STRUC_wmi_obss_scan_enable_cmd_fixed_param, 3082 WMITLV_GET_STRUCT_TLVLEN(wmi_obss_scan_enable_cmd_fixed_param)); 3083 3084 buf_ptr = (uint8_t *) cmd; 3085 3086 cmd->vdev_id = req->bss_id; 3087 cmd->scan_type = req->scan_type; 3088 cmd->obss_scan_active_dwell = 3089 req->obss_active_dwelltime; 3090 cmd->obss_scan_passive_dwell = 3091 req->obss_passive_dwelltime; 3092 cmd->bss_channel_width_trigger_scan_interval = 3093 req->obss_width_trigger_interval; 3094 cmd->bss_width_channel_transition_delay_factor = 3095 req->bsswidth_ch_trans_delay; 3096 cmd->obss_scan_active_total_per_channel = 3097 req->obss_active_total_per_channel; 3098 cmd->obss_scan_passive_total_per_channel = 3099 req->obss_passive_total_per_channel; 3100 cmd->obss_scan_activity_threshold = 3101 req->obss_activity_threshold; 3102 3103 cmd->channel_len = req->channel_count; 3104 cmd->forty_mhz_intolerant = req->fortymhz_intolerent; 3105 cmd->current_operating_class = req->current_operatingclass; 3106 cmd->ie_len = req->iefield_len; 3107 3108 buf_ptr += sizeof(wmi_obss_scan_enable_cmd_fixed_param); 3109 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE, 3110 qdf_roundup(req->channel_count, sizeof(uint32_t))); 3111 3112 buf_ptr += WMI_TLV_HDR_SIZE; 3113 channel_list = (uint8_t *) buf_ptr; 3114 3115 for (i = 0; i < req->channel_count; i++) { 3116 channel_list[i] = 3117 wlan_reg_freq_to_chan(wma->pdev, req->chan_freq_list[i]); 3118 wma_nofl_debug("Ch[%d]: %d ", i, channel_list[i]); 3119 } 3120 3121 buf_ptr += qdf_roundup(sizeof(uint8_t) * req->channel_count, 3122 sizeof(uint32_t)); 3123 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE, 3124 qdf_roundup(1, sizeof(uint32_t))); 3125 buf_ptr += WMI_TLV_HDR_SIZE; 3126 3127 buf_ptr += qdf_roundup(sizeof(uint8_t) * 1, sizeof(uint32_t)); 3128 3129 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32, 3130 sizeof(uint32_t) * req->channel_count); 3131 buf_ptr += WMI_TLV_HDR_SIZE; 3132 3133 chan_freq_list = (uint32_t *)buf_ptr; 3134 for (i = 0; i < req->channel_count; i++) { 3135 chan_freq_list[i] = req->chan_freq_list[i]; 3136 wma_nofl_debug("freq[%u]: %u ", i, chan_freq_list[i]); 3137 } 3138 3139 buf_ptr += sizeof(uint32_t) * req->channel_count; 3140 3141 status = wmi_unified_cmd_send(wma->wmi_handle, buf, len, 3142 WMI_OBSS_SCAN_ENABLE_CMDID); 3143 if (QDF_IS_STATUS_ERROR(status)) 3144 wmi_buf_free(buf); 3145 3146 return status; 3147 } 3148 3149 #ifdef WLAN_FEATURE_ROAM_OFFLOAD 3150 void cm_roam_update_vdev(struct roam_offload_synch_ind *sync_ind, 3151 uint8_t vdev_id) 3152 { 3153 tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA); 3154 3155 if (!wma) 3156 return; 3157 3158 wma_roam_update_vdev(wma, sync_ind, vdev_id); 3159 } 3160 3161 QDF_STATUS 3162 cm_roam_pe_sync_callback(struct roam_offload_synch_ind *sync_ind, 3163 uint8_t vdev_id, uint16_t ie_len) 3164 { 3165 tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA); 3166 struct pe_session *pe_session; 3167 bool new_link_session = false; 3168 QDF_STATUS status; 3169 3170 if (!wma) 3171 return QDF_STATUS_E_INVAL; 3172 3173 pe_session = pe_find_session_by_vdev_id(wma->mac_context, vdev_id); 3174 if (!pe_session) { 3175 new_link_session = true; 3176 /* Legacy to MLO roaming: create new pe session */ 3177 status = lim_create_and_fill_link_session(wma->mac_context, 3178 vdev_id, 3179 sync_ind, ie_len); 3180 3181 if (QDF_IS_STATUS_ERROR(status)) { 3182 wma_err("MLO ROAM: pe session creation failed vdev id %d", 3183 vdev_id); 3184 return status; 3185 } 3186 } 3187 status = wma->pe_roam_synch_cb(wma->mac_context, 3188 vdev_id, sync_ind, ie_len, 3189 SIR_ROAM_SYNCH_PROPAGATION); 3190 3191 /* delete newly added pe session in case of failure */ 3192 if (new_link_session && QDF_IS_STATUS_ERROR(status)) { 3193 pe_session = pe_find_session_by_vdev_id(wma->mac_context, 3194 vdev_id); 3195 if (pe_session) 3196 pe_delete_session(wma->mac_context, pe_session); 3197 } 3198 return status; 3199 } 3200 3201 void cm_update_phymode_on_roam(uint8_t vdev_id, 3202 struct roam_offload_synch_ind *sync_ind) 3203 { 3204 tp_wma_handle wma = cds_get_context(QDF_MODULE_ID_WMA); 3205 struct qdf_mac_addr link_bssid; 3206 wmi_channel link_chan; 3207 3208 if (!wma) 3209 return; 3210 3211 if (is_multi_link_roam(sync_ind)) { 3212 mlo_roam_get_bssid_chan_for_link(vdev_id, sync_ind, 3213 &link_bssid, 3214 &link_chan); 3215 wma_update_phymode_on_roam(wma, &link_bssid, 3216 &link_chan, 3217 &wma->interfaces[vdev_id]); 3218 } else { 3219 wma_update_phymode_on_roam(wma, &sync_ind->bssid, 3220 &sync_ind->chan, 3221 &wma->interfaces[vdev_id]); 3222 } 3223 } 3224 3225 enum wlan_phymode 3226 wlan_cm_fw_to_host_phymode(WMI_HOST_WLAN_PHY_MODE phymode) 3227 { 3228 return wma_fw_to_host_phymode(phymode); 3229 } 3230 #endif 3231 3232 QDF_STATUS 3233 wlan_update_peer_phy_mode(struct wlan_channel *des_chan, 3234 struct wlan_objmgr_vdev *vdev) 3235 { 3236 return wma_update_bss_peer_phy_mode(des_chan, vdev); 3237 } 3238