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