1 /* 2 * Copyright (c) 2012-2021 The Linux Foundation. All rights reserved. 3 * Copyright (c) 2022-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 * This file lim_send_sme_rspMessages.cc contains the functions 22 * for sending SME response/notification messages to applications 23 * above MAC software. 24 * Author: Chandra Modumudi 25 * Date: 02/13/02 26 * History:- 27 * Date Modified by Modification Information 28 * -------------------------------------------------------------------- 29 */ 30 31 #include "qdf_types.h" 32 #include "wni_api.h" 33 #include "sir_common.h" 34 #include "ani_global.h" 35 36 #include "wni_cfg.h" 37 #include "sys_def.h" 38 39 #include "sch_api.h" 40 #include "utils_api.h" 41 #include "lim_utils.h" 42 #include "lim_security_utils.h" 43 #include "lim_ser_des_utils.h" 44 #include "lim_send_sme_rsp_messages.h" 45 #include "lim_session_utils.h" 46 #include "lim_types.h" 47 #include "sir_api.h" 48 #include "cds_regdomain.h" 49 #include "lim_send_messages.h" 50 #include "nan_datapath.h" 51 #include "lim_assoc_utils.h" 52 #include "wlan_reg_services_api.h" 53 #include "wlan_utility.h" 54 55 #include "wlan_tdls_tgt_api.h" 56 #include "lim_process_fils.h" 57 #include "wma.h" 58 #include "wma_he.h" 59 #include <../../core/src/wlan_cm_vdev_api.h> 60 #include <wlan_mlo_mgr_sta.h> 61 #include <spatial_reuse_api.h> 62 #include <wlan_mlo_mgr_cmn.h> 63 64 void lim_send_sme_rsp(struct mac_context *mac_ctx, uint16_t msg_type, 65 tSirResultCodes result_code, uint8_t vdev_id) 66 { 67 struct scheduler_msg msg = {0}; 68 tSirSmeRsp *sme_rsp; 69 70 pe_debug("Sending message: %s with reasonCode: %s", 71 lim_msg_str(msg_type), lim_result_code_str(result_code)); 72 73 sme_rsp = qdf_mem_malloc(sizeof(tSirSmeRsp)); 74 if (!sme_rsp) 75 return; 76 77 sme_rsp->messageType = msg_type; 78 sme_rsp->length = sizeof(tSirSmeRsp); 79 sme_rsp->status_code = result_code; 80 sme_rsp->vdev_id = vdev_id; 81 82 msg.type = msg_type; 83 msg.bodyptr = sme_rsp; 84 msg.bodyval = 0; 85 MTRACE(mac_trace(mac_ctx, TRACE_CODE_TX_SME_MSG, vdev_id, msg.type)); 86 87 lim_sys_process_mmh_msg_api(mac_ctx, &msg); 88 } 89 90 void 91 lim_send_stop_bss_response(struct mac_context *mac_ctx, uint8_t vdev_id, 92 tSirResultCodes result_code) 93 { 94 struct scheduler_msg msg = {0}; 95 struct stop_bss_rsp *stop_bss_rsp; 96 struct pe_session *pe_session; 97 struct pe_session *sta_session; 98 99 pe_debug("Sending stop bss response with reasonCode: %s", 100 lim_result_code_str(result_code)); 101 102 pe_session = pe_find_session_by_vdev_id(mac_ctx, vdev_id); 103 if (!pe_session) { 104 pe_err("Unable to find session for stop bss response"); 105 return; 106 } 107 108 /* 109 * STA LPI + SAP VLP is supported. For this STA should operate in VLP 110 * power level of the SAP. 111 * 112 * For the STA, if the TPC is changed to VLP, then restore the original 113 * power for the STA when SAP disconnects. 114 */ 115 if (wlan_get_tpc_update_required_for_sta(pe_session->vdev)) { 116 sta_session = lim_get_concurrent_session(mac_ctx, vdev_id, 117 pe_session->opmode); 118 if (sta_session && 119 sta_session->curr_op_freq == pe_session->curr_op_freq) 120 lim_update_tx_power(mac_ctx, pe_session, 121 sta_session, true); 122 } 123 124 stop_bss_rsp = qdf_mem_malloc(sizeof(*stop_bss_rsp)); 125 if (!stop_bss_rsp) 126 return; 127 128 stop_bss_rsp->status_code = result_code; 129 stop_bss_rsp->vdev_id = vdev_id; 130 131 msg.type = eWNI_SME_STOP_BSS_RSP; 132 msg.bodyptr = stop_bss_rsp; 133 msg.bodyval = 0; 134 135 #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM /* FEATURE_WLAN_DIAG_SUPPORT */ 136 lim_diag_event_report(mac_ctx, WLAN_PE_DIAG_STOP_BSS_RSP_EVENT, 137 NULL, (uint16_t) result_code, 0); 138 #endif /* FEATURE_WLAN_DIAG_SUPPORT */ 139 lim_sys_process_mmh_msg_api(mac_ctx, &msg); 140 } 141 142 #ifdef WLAN_FEATURE_11AX 143 /** 144 * lim_get_he_rate_info_flag() - Get he tx rate info flag 145 * @sta_ds: Pointer to station ds structure 146 * 147 * This function is called to get the he tx rate info. 148 * 149 * Return: Returns he tx rate flag 150 */ 151 static enum tx_rate_info 152 lim_get_he_rate_info_flag(tpDphHashNode sta_ds) 153 { 154 tDot11fIEhe_cap *peer_he = &sta_ds->he_config; 155 156 if (peer_he->chan_width_3 || peer_he->chan_width_2) 157 return TX_RATE_HE160; 158 else if (peer_he->chan_width_1) 159 return TX_RATE_HE80; 160 else if (peer_he->chan_width_0) 161 return TX_RATE_HE40; 162 else 163 return TX_RATE_HE20; 164 } 165 #else 166 static enum tx_rate_info 167 lim_get_he_rate_info_flag(tpDphHashNode sta_ds) 168 { 169 return TX_RATE_LEGACY; 170 } 171 #endif 172 173 #ifdef WLAN_FEATURE_11BE 174 /** 175 * lim_get_eht_rate_info_flag() - Get eht tx rate info flag 176 * @sta_ds: Pointer to station ds structure 177 * 178 * This function is called to get the eht tx rate info. 179 * 180 * Return: Returns eht tx rate flag 181 */ 182 static enum tx_rate_info 183 lim_get_eht_rate_info_flag(tpDphHashNode sta_ds) 184 { 185 if (sta_ds->eht_config.support_320mhz_6ghz) 186 return TX_RATE_EHT320; 187 else if (sta_ds->ch_width == CH_WIDTH_160MHZ) 188 return TX_RATE_EHT160; 189 else if (sta_ds->ch_width == CH_WIDTH_80MHZ) 190 return TX_RATE_EHT80; 191 else if (sta_ds->ch_width == CH_WIDTH_40MHZ) 192 return TX_RATE_EHT40; 193 else 194 return TX_RATE_EHT20; 195 } 196 #else 197 static enum tx_rate_info 198 lim_get_eht_rate_info_flag(tpDphHashNode sta_ds) 199 { 200 return TX_RATE_LEGACY; 201 } 202 #endif 203 204 /** 205 * lim_get_max_rate_flags() - Get rate flags 206 * @mac_ctx: Pointer to global MAC structure 207 * @sta_ds: Pointer to station ds structure 208 * 209 * This function is called to get the rate flags for a connection 210 * from the station ds structure depending on the ht and the vht 211 * channel width supported. 212 * 213 * Return: Returns the populated rate_flags 214 */ 215 uint32_t lim_get_max_rate_flags(struct mac_context *mac_ctx, tpDphHashNode sta_ds) 216 { 217 uint32_t rate_flags = 0; 218 219 if (!sta_ds) { 220 pe_err("sta_ds is NULL"); 221 return rate_flags; 222 } 223 224 if (!lim_is_sta_eht_capable(sta_ds) && 225 !sta_ds->mlmStaContext.htCapability && 226 !sta_ds->mlmStaContext.vhtCapability && 227 !lim_is_sta_he_capable(sta_ds)) { 228 rate_flags |= TX_RATE_LEGACY; 229 } else { 230 if (lim_is_sta_eht_capable(sta_ds)) { 231 rate_flags |= lim_get_eht_rate_info_flag(sta_ds); 232 } else if (lim_is_sta_he_capable(sta_ds)) { 233 rate_flags |= lim_get_he_rate_info_flag(sta_ds); 234 } else if (sta_ds->mlmStaContext.vhtCapability) { 235 if (WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ == 236 sta_ds->vhtSupportedChannelWidthSet || 237 WNI_CFG_VHT_CHANNEL_WIDTH_80_PLUS_80MHZ == 238 sta_ds->vhtSupportedChannelWidthSet) { 239 rate_flags |= TX_RATE_VHT160; 240 } else if (WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ == 241 sta_ds->vhtSupportedChannelWidthSet) { 242 rate_flags |= TX_RATE_VHT80; 243 } else if (WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ == 244 sta_ds->vhtSupportedChannelWidthSet) { 245 if (sta_ds->htSupportedChannelWidthSet) 246 rate_flags |= TX_RATE_VHT40; 247 else 248 rate_flags |= TX_RATE_VHT20; 249 } 250 } else if (sta_ds->mlmStaContext.htCapability) { 251 if (sta_ds->htSupportedChannelWidthSet) 252 rate_flags |= TX_RATE_HT40; 253 else 254 rate_flags |= TX_RATE_HT20; 255 } 256 } 257 258 if (sta_ds->htShortGI20Mhz || sta_ds->htShortGI40Mhz) 259 rate_flags |= TX_RATE_SGI; 260 261 return rate_flags; 262 } 263 264 static void lim_send_smps_intolerent(struct mac_context *mac_ctx, 265 struct pe_session *pe_session, 266 uint32_t bcn_len, uint8_t *bcn_ptr) 267 { 268 const uint8_t *vendor_ap_1; 269 uint32_t bcn_ie_len; 270 uint8_t *bcn_ie_ptr; 271 272 if (!bcn_ptr || (bcn_len <= (sizeof(struct wlan_frame_hdr) + 273 offsetof(struct wlan_bcn_frame, ie)))) 274 return; 275 276 bcn_ie_len = bcn_len - sizeof(struct wlan_frame_hdr) - 277 offsetof(struct wlan_bcn_frame, ie); 278 bcn_ie_ptr = bcn_ptr + sizeof(struct wlan_frame_hdr) + 279 offsetof(struct wlan_bcn_frame, ie); 280 281 vendor_ap_1 = 282 wlan_get_vendor_ie_ptr_from_oui(SIR_MAC_VENDOR_AP_1_OUI, 283 SIR_MAC_VENDOR_AP_1_OUI_LEN, 284 bcn_ie_ptr, bcn_ie_len); 285 if (mac_ctx->roam.configParam.is_force_1x1 && 286 vendor_ap_1 && (pe_session->nss == 2) && 287 (!mac_ctx->mlme_cfg->gen.as_enabled || 288 wlan_reg_is_5ghz_ch_freq(pe_session->curr_op_freq))) { 289 /* SET vdev param */ 290 pe_debug("sending SMPS intolrent vdev_param"); 291 wma_cli_set_command(pe_session->vdev_id, 292 (int)wmi_vdev_param_smps_intolerant, 293 1, VDEV_CMD); 294 } 295 } 296 297 #ifdef WLAN_FEATURE_FILS_SK 298 static void lim_set_fils_connection(struct wlan_cm_connect_resp *connect_rsp, 299 struct pe_session *session_entry) 300 { 301 if (lim_is_fils_connection(session_entry)) 302 connect_rsp->is_fils_connection = true; 303 pe_debug("is_fils_connection %d", connect_rsp->is_fils_connection); 304 } 305 #else 306 static inline 307 void lim_set_fils_connection(struct wlan_cm_connect_resp *connect_rsp, 308 struct pe_session *session_entry) 309 {} 310 #endif 311 312 #ifdef FEATURE_WLAN_ESE 313 static void lim_copy_tspec_ie(struct pe_session *pe_session, 314 struct cm_vdev_join_rsp *rsp) 315 { 316 if (pe_session->tspecIes) { 317 rsp->tspec_ie.len = pe_session->tspecLen; 318 rsp->tspec_ie.ptr = 319 qdf_mem_malloc(rsp->tspec_ie.len); 320 if (!rsp->tspec_ie.ptr) 321 return; 322 323 qdf_mem_copy(rsp->tspec_ie.ptr, pe_session->tspecIes, 324 rsp->tspec_ie.len); 325 pe_debug("ESE-TspecLen: %d", rsp->tspec_ie.len); 326 } 327 } 328 329 static void lim_free_tspec_ie(struct pe_session *pe_session) 330 { 331 if (pe_session->tspecIes) { 332 qdf_mem_free(pe_session->tspecIes); 333 pe_session->tspecIes = NULL; 334 pe_session->tspecLen = 0; 335 } 336 } 337 #else 338 static inline void lim_copy_tspec_ie(struct pe_session *pe_session, 339 struct cm_vdev_join_rsp *rsp) 340 {} 341 static inline void lim_free_tspec_ie(struct pe_session *pe_session) 342 {} 343 #endif 344 345 static void lim_cm_fill_rsp_from_stads(struct mac_context *mac_ctx, 346 struct pe_session *pe_session, 347 struct cm_vdev_join_rsp *rsp) 348 { 349 tpDphHashNode sta_ds; 350 351 sta_ds = dph_get_hash_entry(mac_ctx, 352 DPH_STA_HASH_INDEX_PEER, 353 &pe_session->dph.dphHashTable); 354 if (!sta_ds) 355 return; 356 357 rsp->nss = sta_ds->nss; 358 } 359 360 static QDF_STATUS 361 lim_cm_prepare_join_rsp_from_pe_session(struct mac_context *mac_ctx, 362 struct pe_session *pe_session, 363 struct cm_vdev_join_rsp *rsp, 364 enum wlan_cm_connect_fail_reason reason, 365 QDF_STATUS connect_status, 366 enum wlan_status_code status_code) 367 { 368 struct wlan_cm_connect_resp *connect_rsp = &rsp->connect_rsp; 369 struct wlan_connect_rsp_ies *connect_ie = &rsp->connect_rsp.connect_ies; 370 uint32_t bcn_len; 371 uint8_t *bcn_ptr; 372 373 connect_rsp->cm_id = pe_session->cm_id; 374 connect_rsp->vdev_id = pe_session->vdev_id; 375 qdf_ether_addr_copy(connect_rsp->bssid.bytes, pe_session->bssId); 376 wlan_cm_connect_resp_fill_mld_addr_from_cm_id(pe_session->vdev, 377 pe_session->cm_id, 378 connect_rsp); 379 connect_rsp->freq = pe_session->curr_op_freq; 380 connect_rsp->connect_status = connect_status; 381 connect_rsp->reason = reason; 382 connect_rsp->status_code = status_code; 383 connect_rsp->ssid.length = 384 QDF_MIN(WLAN_SSID_MAX_LEN, pe_session->ssId.length); 385 qdf_mem_copy(connect_rsp->ssid.ssid, pe_session->ssId.ssId, 386 connect_rsp->ssid.length); 387 388 lim_set_fils_connection(connect_rsp, pe_session); 389 if (pe_session->beacon) { 390 connect_ie->bcn_probe_rsp.len = pe_session->bcnLen; 391 connect_ie->bcn_probe_rsp.ptr = 392 qdf_mem_malloc(connect_ie->bcn_probe_rsp.len); 393 if (!connect_ie->bcn_probe_rsp.ptr) 394 return QDF_STATUS_E_NOMEM; 395 396 qdf_mem_copy(connect_ie->bcn_probe_rsp.ptr, pe_session->beacon, 397 connect_ie->bcn_probe_rsp.len); 398 } 399 bcn_len = connect_ie->bcn_probe_rsp.len; 400 bcn_ptr = connect_ie->bcn_probe_rsp.ptr; 401 402 if (pe_session->assoc_req) { 403 connect_ie->assoc_req.len = pe_session->assocReqLen; 404 connect_ie->assoc_req.ptr = 405 qdf_mem_malloc(connect_ie->assoc_req.len); 406 if (!connect_ie->assoc_req.ptr) 407 return QDF_STATUS_E_NOMEM; 408 409 qdf_mem_copy(connect_ie->assoc_req.ptr, pe_session->assoc_req, 410 connect_ie->assoc_req.len); 411 } 412 413 if (pe_session->assocRsp) { 414 connect_ie->assoc_rsp.len = pe_session->assocRspLen; 415 connect_ie->assoc_rsp.ptr = 416 qdf_mem_malloc(connect_ie->assoc_rsp.len); 417 if (!connect_ie->assoc_rsp.ptr) 418 return QDF_STATUS_E_NOMEM; 419 420 qdf_mem_copy(connect_ie->assoc_rsp.ptr, pe_session->assocRsp, 421 connect_ie->assoc_rsp.len); 422 } 423 connect_rsp->is_wps_connection = pe_session->wps_registration; 424 connect_rsp->is_osen_connection = pe_session->isOSENConnection; 425 426 if (QDF_IS_STATUS_SUCCESS(connect_status)) { 427 connect_rsp->status_code = STATUS_SUCCESS; 428 populate_fils_connect_params(mac_ctx, pe_session, connect_rsp); 429 connect_rsp->aid = pe_session->limAID; 430 431 /* move ric date to cm_vdev_join_rsp to fill in csr session */ 432 if (pe_session->ricData) { 433 rsp->ric_resp_ie.len = pe_session->RICDataLen; 434 rsp->ric_resp_ie.ptr = 435 qdf_mem_malloc(rsp->ric_resp_ie.len); 436 if (!rsp->ric_resp_ie.ptr) 437 return QDF_STATUS_E_NOMEM; 438 439 qdf_mem_copy(rsp->ric_resp_ie.ptr, pe_session->ricData, 440 rsp->ric_resp_ie.len); 441 } 442 443 lim_copy_tspec_ie(pe_session, rsp); 444 445 lim_send_smps_intolerent(mac_ctx, pe_session, bcn_len, bcn_ptr); 446 lim_cm_fill_rsp_from_stads(mac_ctx, pe_session, rsp); 447 rsp->uapsd_mask = pe_session->gUapsdPerAcBitmask; 448 } 449 450 return QDF_STATUS_SUCCESS; 451 } 452 453 static void 454 lim_cm_fill_join_rsp_from_connect_req(struct cm_vdev_join_req *req, 455 struct cm_vdev_join_rsp *rsp, 456 enum wlan_cm_connect_fail_reason reason) 457 { 458 struct wlan_cm_connect_resp *connect_rsp = &rsp->connect_rsp; 459 460 connect_rsp->cm_id = req->cm_id; 461 connect_rsp->vdev_id = req->vdev_id; 462 qdf_copy_macaddr(&connect_rsp->bssid, &req->entry->bssid); 463 connect_rsp->freq = req->entry->channel.chan_freq; 464 connect_rsp->connect_status = QDF_STATUS_E_FAILURE; 465 connect_rsp->reason = reason; 466 connect_rsp->ssid = req->entry->ssid; 467 connect_rsp->is_wps_connection = req->is_wps_connection; 468 connect_rsp->is_osen_connection = req->is_osen_connection; 469 wlan_cm_connect_resp_fill_mld_addr_from_vdev_id(rsp->psoc, req->vdev_id, 470 req->entry, 471 connect_rsp); 472 } 473 474 static QDF_STATUS lim_cm_flush_connect_rsp(struct scheduler_msg *msg) 475 { 476 struct cm_vdev_join_rsp *rsp; 477 478 if (!msg || !msg->bodyptr) 479 return QDF_STATUS_E_INVAL; 480 481 rsp = msg->bodyptr; 482 wlan_cm_free_connect_rsp(rsp); 483 484 return QDF_STATUS_SUCCESS; 485 } 486 487 static void lim_free_pession_ies(struct pe_session *pe_session) 488 { 489 if (pe_session->beacon) { 490 qdf_mem_free(pe_session->beacon); 491 pe_session->beacon = NULL; 492 pe_session->bcnLen = 0; 493 } 494 if (pe_session->assoc_req) { 495 qdf_mem_free(pe_session->assoc_req); 496 pe_session->assoc_req = NULL; 497 pe_session->assocReqLen = 0; 498 } 499 if (pe_session->assocRsp) { 500 qdf_mem_free(pe_session->assocRsp); 501 pe_session->assocRsp = NULL; 502 pe_session->assocRspLen = 0; 503 } 504 if (pe_session->ricData) { 505 qdf_mem_free(pe_session->ricData); 506 pe_session->ricData = NULL; 507 pe_session->RICDataLen = 0; 508 } 509 lim_free_tspec_ie(pe_session); 510 } 511 512 #ifdef WLAN_FEATURE_11BE_MLO 513 static void lim_copy_ml_partner_info(struct cm_vdev_join_rsp *rsp, 514 struct pe_session *pe_session) 515 { 516 int i; 517 struct mlo_partner_info *partner_info; 518 struct mlo_partner_info *rsp_partner_info; 519 uint8_t chan = 0, op_class, link_id; 520 521 partner_info = &pe_session->ml_partner_info; 522 rsp_partner_info = &rsp->connect_rsp.ml_parnter_info; 523 524 rsp_partner_info->num_partner_links = partner_info->num_partner_links; 525 526 for (i = 0; i < rsp_partner_info->num_partner_links; i++) { 527 link_id = partner_info->partner_link_info[i].link_id; 528 rsp_partner_info->partner_link_info[i].link_id = link_id; 529 qdf_copy_macaddr( 530 &rsp_partner_info->partner_link_info[i].link_addr, 531 &partner_info->partner_link_info[i].link_addr); 532 533 wlan_get_chan_by_bssid_from_rnr( 534 pe_session->vdev, 535 pe_session->cm_id, 536 &partner_info->partner_link_info[i].link_addr, 537 &chan, &op_class); 538 if (!chan) 539 wlan_get_chan_by_link_id_from_rnr( 540 pe_session->vdev, 541 pe_session->cm_id, 542 link_id, &chan, &op_class); 543 if (chan) { 544 rsp_partner_info->partner_link_info[i].chan_freq = 545 wlan_reg_chan_opclass_to_freq_auto(chan, 546 op_class, 547 false); 548 } else { 549 pe_debug("Failed to get channel info for link ID:%d", 550 link_id); 551 } 552 } 553 } 554 #else /* WLAN_FEATURE_11BE_MLO */ 555 static inline void 556 lim_copy_ml_partner_info(struct cm_vdev_join_rsp *rsp, 557 struct pe_session *pe_session) 558 { 559 } 560 #endif /* WLAN_FEATURE_11BE_MLO */ 561 562 void lim_cm_send_connect_rsp(struct mac_context *mac_ctx, 563 struct pe_session *pe_session, 564 struct cm_vdev_join_req *req, 565 enum wlan_cm_connect_fail_reason reason, 566 QDF_STATUS connect_status, 567 enum wlan_status_code status_code, 568 bool is_reassoc) 569 { 570 struct cm_vdev_join_rsp *rsp; 571 QDF_STATUS status; 572 struct scheduler_msg msg; 573 574 if (!pe_session && !req) 575 return; 576 577 rsp = qdf_mem_malloc(sizeof(*rsp)); 578 if (!rsp) 579 return; 580 581 rsp->psoc = mac_ctx->psoc; 582 583 if (!pe_session) { 584 lim_cm_fill_join_rsp_from_connect_req(req, rsp, reason); 585 } else { 586 status = 587 lim_cm_prepare_join_rsp_from_pe_session(mac_ctx, 588 pe_session, 589 rsp, 590 reason, 591 connect_status, 592 status_code); 593 lim_free_pession_ies(pe_session); 594 lim_copy_ml_partner_info(rsp, pe_session); 595 if (QDF_IS_STATUS_ERROR(status)) { 596 pe_err("vdev_id: %d cm_id 0x%x : fail to prepare rsp", 597 rsp->connect_rsp.vdev_id, 598 rsp->connect_rsp.cm_id); 599 wlan_cm_free_connect_rsp(rsp); 600 return; 601 } 602 } 603 604 rsp->connect_rsp.is_reassoc = is_reassoc; 605 qdf_mem_zero(&msg, sizeof(msg)); 606 607 msg.bodyptr = rsp; 608 msg.callback = wlan_cm_send_connect_rsp; 609 msg.flush_callback = lim_cm_flush_connect_rsp; 610 611 status = scheduler_post_message(QDF_MODULE_ID_PE, 612 QDF_MODULE_ID_OS_IF, 613 QDF_MODULE_ID_OS_IF, &msg); 614 615 if (QDF_IS_STATUS_ERROR(status)) { 616 pe_err("vdev_id: %d cm_id 0x%x : msg post fails", 617 rsp->connect_rsp.vdev_id, rsp->connect_rsp.cm_id); 618 wlan_cm_free_connect_rsp(rsp); 619 } 620 } 621 622 static enum wlan_cm_connect_fail_reason 623 lim_cm_get_fail_reason_from_result_code(tSirResultCodes result_code) 624 { 625 enum wlan_cm_connect_fail_reason fail_reason; 626 627 switch (result_code) { 628 case eSIR_SME_JOIN_TIMEOUT_RESULT_CODE: 629 fail_reason = CM_JOIN_TIMEOUT; 630 break; 631 case eSIR_SME_AUTH_TIMEOUT_RESULT_CODE: 632 fail_reason = CM_AUTH_TIMEOUT; 633 break; 634 case eSIR_SME_ASSOC_TIMEOUT_RESULT_CODE: 635 case eSIR_SME_REASSOC_TIMEOUT_RESULT_CODE: 636 case eSIR_SME_FT_REASSOC_TIMEOUT_FAILURE: 637 fail_reason = CM_ASSOC_TIMEOUT; 638 break; 639 case eSIR_SME_AUTH_REFUSED: 640 case eSIR_SME_INVALID_WEP_DEFAULT_KEY: 641 fail_reason = CM_AUTH_FAILED; 642 break; 643 case eSIR_SME_ASSOC_REFUSED: 644 case eSIR_SME_REASSOC_REFUSED: 645 case eSIR_SME_FT_REASSOC_FAILURE: 646 case eSIR_SME_INVALID_ASSOC_RSP_RXED: 647 case eSIR_SME_JOIN_DEAUTH_FROM_AP_DURING_ADD_STA: 648 fail_reason = CM_ASSOC_FAILED; 649 break; 650 default: 651 fail_reason = CM_JOIN_FAILED; 652 break; 653 } 654 655 return fail_reason; 656 } 657 658 #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM 659 static 660 void lim_send_assoc_rsp_diag_event(struct mac_context *mac_ctx, 661 struct pe_session *session_entry, 662 uint16_t msg_type, uint16_t result_code) 663 { 664 if (msg_type == eWNI_SME_REASSOC_RSP) 665 lim_diag_event_report(mac_ctx, WLAN_PE_DIAG_REASSOC_RSP_EVENT, 666 session_entry, result_code, 0); 667 else 668 lim_diag_event_report(mac_ctx, WLAN_PE_DIAG_JOIN_RSP_EVENT, 669 session_entry, result_code, 0); 670 } 671 #else 672 static inline 673 void lim_send_assoc_rsp_diag_event(struct mac_context *mac_ctx, 674 struct pe_session *session_entry, 675 uint16_t msg_type, uint16_t result_code) 676 {} 677 #endif 678 679 void lim_send_sme_join_reassoc_rsp(struct mac_context *mac_ctx, 680 uint16_t msg_type, 681 tSirResultCodes result_code, 682 uint16_t prot_status_code, 683 struct pe_session *session_entry, 684 uint8_t vdev_id) 685 { 686 QDF_STATUS connect_status; 687 enum wlan_cm_connect_fail_reason fail_reason = 0; 688 689 lim_send_assoc_rsp_diag_event(mac_ctx, session_entry, msg_type, 690 result_code); 691 692 pe_debug("Sending message: %s with reasonCode: %s", 693 lim_msg_str(msg_type), lim_result_code_str(result_code)); 694 695 if (result_code == eSIR_SME_SUCCESS) { 696 connect_status = QDF_STATUS_SUCCESS; 697 } else { 698 connect_status = QDF_STATUS_E_FAILURE; 699 fail_reason = 700 lim_cm_get_fail_reason_from_result_code(result_code); 701 } 702 703 return lim_cm_send_connect_rsp(mac_ctx, session_entry, NULL, 704 fail_reason, connect_status, 705 prot_status_code, 706 msg_type == eWNI_SME_JOIN_RSP ? 707 false : true); 708 709 /* add reassoc resp API */ 710 } 711 712 void lim_send_sme_start_bss_rsp(struct mac_context *mac, 713 tSirResultCodes resultCode, 714 struct pe_session *pe_session, 715 uint8_t smesessionId) 716 { 717 718 struct scheduler_msg mmhMsg = {0}; 719 struct start_bss_rsp *start_bss_rsp; 720 721 pe_debug("Sending start bss response with reasonCode: %s", 722 lim_result_code_str(resultCode)); 723 724 start_bss_rsp = qdf_mem_malloc(sizeof(*start_bss_rsp)); 725 if (!start_bss_rsp) 726 return; 727 start_bss_rsp->vdev_id = smesessionId; 728 start_bss_rsp->status_code = resultCode; 729 730 mmhMsg.type = eWNI_SME_START_BSS_RSP; 731 mmhMsg.bodyptr = start_bss_rsp; 732 mmhMsg.bodyval = 0; 733 if (!pe_session) { 734 MTRACE(mac_trace(mac, TRACE_CODE_TX_SME_MSG, 735 NO_SESSION, mmhMsg.type)); 736 } else { 737 MTRACE(mac_trace(mac, TRACE_CODE_TX_SME_MSG, 738 pe_session->peSessionId, mmhMsg.type)); 739 } 740 #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM /* FEATURE_WLAN_DIAG_SUPPORT */ 741 lim_diag_event_report(mac, WLAN_PE_DIAG_START_BSS_RSP_EVENT, 742 pe_session, (uint16_t) resultCode, 0); 743 #endif /* FEATURE_WLAN_DIAG_SUPPORT */ 744 745 lim_sys_process_mmh_msg_api(mac, &mmhMsg); 746 } /*** end lim_send_sme_start_bss_rsp() ***/ 747 748 static void lim_send_sta_disconnect_ind(struct mac_context *mac, 749 struct scheduler_msg *msg) 750 { 751 struct cm_vdev_discon_ind *ind; 752 struct disassoc_ind *disassoc; 753 struct deauth_ind *deauth; 754 struct scheduler_msg ind_msg = {0}; 755 QDF_STATUS status; 756 757 ind = qdf_mem_malloc(sizeof(*ind)); 758 if (!ind) { 759 qdf_mem_free(msg->bodyptr); 760 return; 761 } 762 763 ind->psoc = mac->psoc; 764 if (msg->type == eWNI_SME_DISASSOC_IND) { 765 disassoc = (struct disassoc_ind *)msg->bodyptr; 766 ind->disconnect_param.vdev_id = disassoc->vdev_id; 767 ind->disconnect_param.bssid = disassoc->bssid; 768 ind->disconnect_param.reason_code = disassoc->reasonCode; 769 if (disassoc->from_ap) 770 ind->disconnect_param.source = CM_PEER_DISCONNECT; 771 else 772 ind->disconnect_param.source = CM_SB_DISCONNECT; 773 } else { 774 deauth = (struct deauth_ind *)msg->bodyptr; 775 ind->disconnect_param.vdev_id = deauth->vdev_id; 776 ind->disconnect_param.bssid = deauth->bssid; 777 ind->disconnect_param.reason_code = deauth->reasonCode; 778 if (deauth->from_ap) 779 ind->disconnect_param.source = CM_PEER_DISCONNECT; 780 else 781 ind->disconnect_param.source = CM_SB_DISCONNECT; 782 } 783 ind_msg.bodyptr = ind; 784 ind_msg.callback = cm_send_sb_disconnect_req; 785 ind_msg.type = msg->type; 786 qdf_mem_free(msg->bodyptr); 787 788 status = scheduler_post_message(QDF_MODULE_ID_PE, QDF_MODULE_ID_OS_IF, 789 QDF_MODULE_ID_OS_IF, &ind_msg); 790 791 if (QDF_IS_STATUS_ERROR(status)) { 792 pe_err("vdev_id: %d, source %d, reason %d, type %d msg post fails", 793 ind->disconnect_param.vdev_id, 794 ind->disconnect_param.source, 795 ind->disconnect_param.reason_code, ind_msg.type); 796 qdf_mem_free(ind); 797 } 798 } 799 800 void lim_cm_send_disconnect_rsp(struct mac_context *mac_ctx, uint8_t vdev_id) 801 { 802 QDF_STATUS status; 803 struct scheduler_msg rsp_msg = {0}; 804 struct cm_vdev_disconnect_rsp *rsp; 805 806 rsp = qdf_mem_malloc(sizeof(*rsp)); 807 if (!rsp) 808 return; 809 810 rsp->vdev_id = vdev_id; 811 rsp->psoc = mac_ctx->psoc; 812 813 rsp_msg.bodyptr = rsp; 814 rsp_msg.callback = cm_handle_disconnect_resp; 815 816 status = scheduler_post_message(QDF_MODULE_ID_PE, QDF_MODULE_ID_OS_IF, 817 QDF_MODULE_ID_OS_IF, &rsp_msg); 818 819 if (QDF_IS_STATUS_ERROR(status)) { 820 pe_err("Failed to post disconnect rsp to sme vdev_id %d", 821 vdev_id); 822 qdf_mem_free(rsp); 823 } 824 } 825 826 static void lim_sap_send_sme_disassoc_deauth_ntf(struct mac_context *mac, 827 QDF_STATUS status, 828 uint32_t *pCtx) 829 { 830 struct scheduler_msg mmhMsg = {0}; 831 struct scheduler_msg *pMsg = (struct scheduler_msg *)pCtx; 832 833 mmhMsg.type = pMsg->type; 834 mmhMsg.bodyptr = pMsg; 835 mmhMsg.bodyval = 0; 836 837 MTRACE(mac_trace(mac, TRACE_CODE_TX_SME_MSG, NO_SESSION, mmhMsg.type)); 838 839 lim_sys_process_mmh_msg_api(mac, &mmhMsg); 840 } 841 842 void lim_send_sme_disassoc_deauth_ntf(struct mac_context *mac, 843 QDF_STATUS status, uint32_t *pCtx) 844 { 845 struct scheduler_msg *msg = (struct scheduler_msg *)pCtx; 846 struct disassoc_rsp *disassoc; 847 struct deauth_rsp *deauth; 848 struct sir_sme_discon_done_ind *discon; 849 uint8_t vdev_id; 850 enum QDF_OPMODE opmode; 851 852 switch (msg->type) { 853 case eWNI_SME_DISASSOC_RSP: 854 disassoc = (struct disassoc_rsp *)pCtx; 855 vdev_id = disassoc->sessionId; 856 break; 857 case eWNI_SME_DEAUTH_RSP: 858 deauth = (struct deauth_rsp *)pCtx; 859 vdev_id = deauth->sessionId; 860 break; 861 case eWNI_SME_DISCONNECT_DONE_IND: 862 discon = (struct sir_sme_discon_done_ind *)pCtx; 863 vdev_id = discon->session_id; 864 break; 865 default: 866 pe_err("Received invalid disconnect rsp type %d", msg->type); 867 qdf_mem_free(pCtx); 868 return; 869 } 870 871 opmode = wlan_get_opmode_from_vdev_id(mac->pdev, vdev_id); 872 /* Use connection manager for STA and CLI */ 873 if (opmode == QDF_STA_MODE || opmode == QDF_P2P_CLIENT_MODE) { 874 qdf_mem_free(pCtx); 875 lim_cm_send_disconnect_rsp(mac, vdev_id); 876 return; 877 } 878 879 lim_sap_send_sme_disassoc_deauth_ntf(mac, status, pCtx); 880 } 881 882 void lim_send_sme_disassoc_ntf(struct mac_context *mac, 883 tSirMacAddr peerMacAddr, 884 tSirResultCodes reasonCode, 885 uint16_t disassocTrigger, 886 uint16_t aid, 887 uint8_t smesessionId, 888 struct pe_session *pe_session) 889 { 890 struct disassoc_rsp *pSirSmeDisassocRsp; 891 struct disassoc_ind *pSirSmeDisassocInd = NULL; 892 uint32_t *pMsg = NULL; 893 bool failure = false; 894 struct pe_session *session = NULL; 895 uint16_t i, assoc_id; 896 tpDphHashNode sta_ds = NULL; 897 QDF_STATUS status; 898 enum QDF_OPMODE opmode; 899 900 pe_debug("Disassoc Ntf with trigger : %d reasonCode: %d", 901 disassocTrigger, reasonCode); 902 903 switch (disassocTrigger) { 904 case eLIM_DUPLICATE_ENTRY: 905 /* 906 * Duplicate entry is removed at LIM. 907 * Initiate new entry for other session 908 */ 909 pe_debug("Rcvd eLIM_DUPLICATE_ENTRY for " QDF_MAC_ADDR_FMT, 910 QDF_MAC_ADDR_REF(peerMacAddr)); 911 912 for (i = 0; i < mac->lim.maxBssId; i++) { 913 session = &mac->lim.gpSession[i]; 914 if (session->valid && 915 (session->opmode == QDF_SAP_MODE)) { 916 /* Find the sta ds entry in another session */ 917 sta_ds = dph_lookup_hash_entry(mac, 918 peerMacAddr, &assoc_id, 919 &session->dph.dphHashTable); 920 if (sta_ds) 921 break; 922 } 923 } 924 if (sta_ds) { 925 if (lim_add_sta(mac, sta_ds, false, session) != 926 QDF_STATUS_SUCCESS) 927 pe_err("could not Add STA with assocId: %d", 928 sta_ds->assocId); 929 } 930 status = lim_prepare_disconnect_done_ind(mac, &pMsg, 931 smesessionId, 932 reasonCode, 933 &peerMacAddr[0]); 934 if (!QDF_IS_STATUS_SUCCESS(status)) { 935 pe_err("Failed to prepare message"); 936 return; 937 } 938 break; 939 940 case eLIM_HOST_DISASSOC: 941 /** 942 * Disassociation response due to 943 * host triggered disassociation 944 */ 945 946 pSirSmeDisassocRsp = qdf_mem_malloc(sizeof(struct disassoc_rsp)); 947 if (!pSirSmeDisassocRsp) { 948 failure = true; 949 goto error; 950 } 951 pe_debug("send eWNI_SME_DISASSOC_RSP with retCode: %d for " 952 QDF_MAC_ADDR_FMT, 953 reasonCode, QDF_MAC_ADDR_REF(peerMacAddr)); 954 pSirSmeDisassocRsp->messageType = eWNI_SME_DISASSOC_RSP; 955 pSirSmeDisassocRsp->length = sizeof(struct disassoc_rsp); 956 pSirSmeDisassocRsp->sessionId = smesessionId; 957 pSirSmeDisassocRsp->status_code = reasonCode; 958 qdf_mem_copy(pSirSmeDisassocRsp->peer_macaddr.bytes, 959 peerMacAddr, sizeof(tSirMacAddr)); 960 961 #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM /* FEATURE_WLAN_DIAG_SUPPORT */ 962 963 lim_diag_event_report(mac, WLAN_PE_DIAG_DISASSOC_RSP_EVENT, 964 pe_session, (uint16_t) reasonCode, 0); 965 #endif 966 pMsg = (uint32_t *) pSirSmeDisassocRsp; 967 break; 968 969 case eLIM_PEER_ENTITY_DISASSOC: 970 case eLIM_LINK_MONITORING_DISASSOC: 971 status = lim_prepare_disconnect_done_ind(mac, &pMsg, 972 smesessionId, 973 reasonCode, &peerMacAddr[0]); 974 if (!QDF_IS_STATUS_SUCCESS(status)) { 975 pe_err("Failed to prepare message"); 976 return; 977 } 978 break; 979 980 default: 981 /** 982 * Disassociation indication due to Disassociation 983 * frame reception from peer entity or due to 984 * loss of link with peer entity. 985 */ 986 pSirSmeDisassocInd = 987 qdf_mem_malloc(sizeof(*pSirSmeDisassocInd)); 988 if (!pSirSmeDisassocInd) { 989 failure = true; 990 goto error; 991 } 992 pe_debug("send eWNI_SME_DISASSOC_IND with retCode: %d for " 993 QDF_MAC_ADDR_FMT, 994 reasonCode, QDF_MAC_ADDR_REF(peerMacAddr)); 995 pSirSmeDisassocInd->messageType = eWNI_SME_DISASSOC_IND; 996 pSirSmeDisassocInd->length = sizeof(*pSirSmeDisassocInd); 997 pSirSmeDisassocInd->vdev_id = smesessionId; 998 pSirSmeDisassocInd->reasonCode = reasonCode; 999 pSirSmeDisassocInd->status_code = reasonCode; 1000 qdf_mem_copy(pSirSmeDisassocInd->bssid.bytes, 1001 pe_session->bssId, sizeof(tSirMacAddr)); 1002 qdf_mem_copy(pSirSmeDisassocInd->peer_macaddr.bytes, 1003 peerMacAddr, sizeof(tSirMacAddr)); 1004 1005 #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM /* FEATURE_WLAN_DIAG_SUPPORT */ 1006 lim_diag_event_report(mac, WLAN_PE_DIAG_DISASSOC_IND_EVENT, 1007 pe_session, (uint16_t) reasonCode, 0); 1008 #endif 1009 pMsg = (uint32_t *) pSirSmeDisassocInd; 1010 1011 break; 1012 } 1013 1014 error: 1015 /* Delete the PE session Created */ 1016 if ((pe_session) && LIM_IS_STA_ROLE(pe_session)) 1017 pe_delete_session(mac, pe_session); 1018 1019 if (failure) 1020 return; 1021 1022 opmode = wlan_get_opmode_from_vdev_id(mac->pdev, smesessionId); 1023 if ((opmode == QDF_STA_MODE || opmode == QDF_P2P_CLIENT_MODE) && 1024 pSirSmeDisassocInd && 1025 pSirSmeDisassocInd->messageType == eWNI_SME_DISASSOC_IND) { 1026 struct scheduler_msg msg = {0}; 1027 1028 msg.type = pSirSmeDisassocInd->messageType; 1029 msg.bodyptr = pSirSmeDisassocInd; 1030 1031 return lim_send_sta_disconnect_ind(mac, &msg); 1032 } 1033 1034 lim_send_sme_disassoc_deauth_ntf(mac, QDF_STATUS_SUCCESS, 1035 (uint32_t *)pMsg); 1036 } /*** end lim_send_sme_disassoc_ntf() ***/ 1037 1038 static bool lim_is_disconnect_from_ap(enum eLimDisassocTrigger trigger) 1039 { 1040 if (trigger == eLIM_PEER_ENTITY_DEAUTH || 1041 trigger == eLIM_PEER_ENTITY_DISASSOC) 1042 return true; 1043 1044 return false; 1045 } 1046 1047 /** ----------------------------------------------------------------- 1048 \brief lim_send_sme_disassoc_ind() - sends SME_DISASSOC_IND 1049 1050 After receiving disassociation frame from peer entity, this 1051 function sends a eWNI_SME_DISASSOC_IND to SME with a specific 1052 reason code. 1053 1054 \param mac - global mac structure 1055 \param sta - station dph hash node 1056 \return none 1057 \sa 1058 ----------------------------------------------------------------- */ 1059 void 1060 lim_send_sme_disassoc_ind(struct mac_context *mac, tpDphHashNode sta, 1061 struct pe_session *pe_session) 1062 { 1063 struct scheduler_msg mmhMsg = {0}; 1064 struct disassoc_ind *pSirSmeDisassocInd; 1065 1066 pSirSmeDisassocInd = qdf_mem_malloc(sizeof(*pSirSmeDisassocInd)); 1067 if (!pSirSmeDisassocInd) 1068 return; 1069 1070 pSirSmeDisassocInd->messageType = eWNI_SME_DISASSOC_IND; 1071 pSirSmeDisassocInd->length = sizeof(*pSirSmeDisassocInd); 1072 1073 pSirSmeDisassocInd->vdev_id = pe_session->smeSessionId; 1074 pSirSmeDisassocInd->status_code = eSIR_SME_DEAUTH_STATUS; 1075 pSirSmeDisassocInd->reasonCode = sta->mlmStaContext.disassocReason; 1076 1077 qdf_mem_copy(pSirSmeDisassocInd->bssid.bytes, pe_session->bssId, 1078 QDF_MAC_ADDR_SIZE); 1079 1080 qdf_mem_copy(pSirSmeDisassocInd->peer_macaddr.bytes, sta->staAddr, 1081 QDF_MAC_ADDR_SIZE); 1082 1083 if (LIM_IS_STA_ROLE(pe_session)) 1084 pSirSmeDisassocInd->from_ap = 1085 lim_is_disconnect_from_ap(sta->mlmStaContext.cleanupTrigger); 1086 1087 mmhMsg.type = eWNI_SME_DISASSOC_IND; 1088 mmhMsg.bodyptr = pSirSmeDisassocInd; 1089 mmhMsg.bodyval = 0; 1090 1091 MTRACE(mac_trace(mac, TRACE_CODE_TX_SME_MSG, 1092 pe_session->peSessionId, mmhMsg.type)); 1093 #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM /* FEATURE_WLAN_DIAG_SUPPORT */ 1094 lim_diag_event_report(mac, WLAN_PE_DIAG_DISASSOC_IND_EVENT, pe_session, 1095 0, (uint16_t) sta->mlmStaContext.disassocReason); 1096 #endif /* FEATURE_WLAN_DIAG_SUPPORT */ 1097 1098 if (LIM_IS_STA_ROLE(pe_session)) 1099 return lim_send_sta_disconnect_ind(mac, &mmhMsg); 1100 1101 lim_sys_process_mmh_msg_api(mac, &mmhMsg); 1102 1103 } /*** end lim_send_sme_disassoc_ind() ***/ 1104 1105 /** ----------------------------------------------------------------- 1106 \brief lim_send_sme_deauth_ind() - sends SME_DEAUTH_IND 1107 1108 After receiving deauthentication frame from peer entity, this 1109 function sends a eWNI_SME_DEAUTH_IND to SME with a specific 1110 reason code. 1111 1112 \param mac - global mac structure 1113 \param sta - station dph hash node 1114 \return none 1115 \sa 1116 ----------------------------------------------------------------- */ 1117 void 1118 lim_send_sme_deauth_ind(struct mac_context *mac, tpDphHashNode sta, 1119 struct pe_session *pe_session) 1120 { 1121 struct scheduler_msg mmhMsg = {0}; 1122 struct deauth_ind *pSirSmeDeauthInd; 1123 1124 pSirSmeDeauthInd = qdf_mem_malloc(sizeof(*pSirSmeDeauthInd)); 1125 if (!pSirSmeDeauthInd) 1126 return; 1127 1128 pSirSmeDeauthInd->messageType = eWNI_SME_DEAUTH_IND; 1129 pSirSmeDeauthInd->length = sizeof(*pSirSmeDeauthInd); 1130 1131 pSirSmeDeauthInd->vdev_id = pe_session->smeSessionId; 1132 if (eSIR_INFRA_AP_MODE == pe_session->bssType) { 1133 pSirSmeDeauthInd->status_code = 1134 (tSirResultCodes) sta->mlmStaContext.cleanupTrigger; 1135 } else { 1136 /* Need to indicate the reason code over the air */ 1137 pSirSmeDeauthInd->status_code = 1138 (tSirResultCodes) sta->mlmStaContext.disassocReason; 1139 } 1140 /* BSSID */ 1141 qdf_mem_copy(pSirSmeDeauthInd->bssid.bytes, pe_session->bssId, 1142 QDF_MAC_ADDR_SIZE); 1143 /* peerMacAddr */ 1144 qdf_mem_copy(pSirSmeDeauthInd->peer_macaddr.bytes, sta->staAddr, 1145 QDF_MAC_ADDR_SIZE); 1146 pSirSmeDeauthInd->reasonCode = sta->mlmStaContext.disassocReason; 1147 1148 if (sta->mlmStaContext.disassocReason == REASON_STA_LEAVING) 1149 pSirSmeDeauthInd->rssi = sta->del_sta_ctx_rssi; 1150 1151 if (LIM_IS_STA_ROLE(pe_session)) 1152 pSirSmeDeauthInd->from_ap = 1153 lim_is_disconnect_from_ap(sta->mlmStaContext.cleanupTrigger); 1154 1155 mmhMsg.type = eWNI_SME_DEAUTH_IND; 1156 mmhMsg.bodyptr = pSirSmeDeauthInd; 1157 mmhMsg.bodyval = 0; 1158 1159 MTRACE(mac_trace_msg_tx(mac, pe_session->peSessionId, mmhMsg.type)); 1160 #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM /* FEATURE_WLAN_DIAG_SUPPORT */ 1161 lim_diag_event_report(mac, WLAN_PE_DIAG_DEAUTH_IND_EVENT, pe_session, 1162 0, sta->mlmStaContext.cleanupTrigger); 1163 #endif /* FEATURE_WLAN_DIAG_SUPPORT */ 1164 1165 if (LIM_IS_STA_ROLE(pe_session)) 1166 return lim_send_sta_disconnect_ind(mac, &mmhMsg); 1167 1168 lim_sys_process_mmh_msg_api(mac, &mmhMsg); 1169 return; 1170 } /*** end lim_send_sme_deauth_ind() ***/ 1171 1172 #ifdef FEATURE_WLAN_TDLS 1173 /** 1174 * lim_send_sme_tdls_del_sta_ind() 1175 * 1176 ***FUNCTION: 1177 * This function is called to send the TDLS STA context deletion to SME. 1178 * 1179 ***LOGIC: 1180 * 1181 ***ASSUMPTIONS: 1182 * 1183 ***NOTE: 1184 * NA 1185 * 1186 * @param mac - Pointer to global MAC structure 1187 * @param sta - Pointer to internal STA Datastructure 1188 * @param pe_session - Pointer to the session entry 1189 * @param reasonCode - Reason for TDLS sta deletion 1190 * @return None 1191 */ 1192 void 1193 lim_send_sme_tdls_del_sta_ind(struct mac_context *mac, tpDphHashNode sta, 1194 struct pe_session *pe_session, uint16_t reasonCode) 1195 { 1196 struct tdls_event_info info; 1197 1198 pe_debug("Delete TDLS Peer "QDF_MAC_ADDR_FMT "with reason code: %d", 1199 QDF_MAC_ADDR_REF(sta->staAddr), reasonCode); 1200 info.vdev_id = pe_session->smeSessionId; 1201 qdf_mem_copy(info.peermac.bytes, sta->staAddr, QDF_MAC_ADDR_SIZE); 1202 info.message_type = TDLS_PEER_DISCONNECTED; 1203 info.peer_reason = TDLS_DISCONNECTED_PEER_DELETE; 1204 1205 tgt_tdls_event_handler(mac->psoc, &info); 1206 1207 return; 1208 } /*** end lim_send_sme_tdls_del_sta_ind() ***/ 1209 1210 /** 1211 * lim_send_sme_mgmt_tx_completion() 1212 * 1213 ***FUNCTION: 1214 * This function is called to send the eWNI_SME_MGMT_FRM_TX_COMPLETION_IND 1215 * message to SME. 1216 * 1217 ***LOGIC: 1218 * 1219 ***ASSUMPTIONS: 1220 * 1221 ***NOTE: 1222 * NA 1223 * 1224 * @param mac - Pointer to global MAC structure 1225 * @param pe_session - Pointer to the session entry 1226 * @param txCompleteStatus - TX Complete Status of Mgmt Frames 1227 * @return None 1228 */ 1229 void 1230 lim_send_sme_mgmt_tx_completion(struct mac_context *mac, 1231 uint32_t vdev_id, 1232 uint32_t txCompleteStatus) 1233 { 1234 struct scheduler_msg msg = {0}; 1235 struct tdls_mgmt_tx_completion_ind *mgmt_tx_completion_ind; 1236 QDF_STATUS status; 1237 1238 mgmt_tx_completion_ind = 1239 qdf_mem_malloc(sizeof(*mgmt_tx_completion_ind)); 1240 if (!mgmt_tx_completion_ind) 1241 return; 1242 1243 /* sessionId */ 1244 mgmt_tx_completion_ind->vdev_id = vdev_id; 1245 1246 mgmt_tx_completion_ind->tx_complete_status = txCompleteStatus; 1247 1248 msg.type = eWNI_SME_MGMT_FRM_TX_COMPLETION_IND; 1249 msg.bodyptr = mgmt_tx_completion_ind; 1250 msg.bodyval = 0; 1251 1252 mgmt_tx_completion_ind->psoc = mac->psoc; 1253 msg.callback = tgt_tdls_send_mgmt_tx_completion; 1254 status = scheduler_post_message(QDF_MODULE_ID_PE, 1255 QDF_MODULE_ID_TDLS, 1256 QDF_MODULE_ID_TARGET_IF, &msg); 1257 if (QDF_IS_STATUS_ERROR(status)) { 1258 pe_err("post msg fail, %d", status); 1259 qdf_mem_free(mgmt_tx_completion_ind); 1260 } 1261 } /*** end lim_send_sme_tdls_delete_all_peer_ind() ***/ 1262 1263 #endif /* FEATURE_WLAN_TDLS */ 1264 1265 QDF_STATUS lim_prepare_disconnect_done_ind(struct mac_context *mac_ctx, 1266 uint32_t **msg, 1267 uint8_t session_id, 1268 tSirResultCodes reason_code, 1269 uint8_t *peer_mac_addr) 1270 { 1271 struct sir_sme_discon_done_ind *sir_sme_dis_ind; 1272 1273 sir_sme_dis_ind = qdf_mem_malloc(sizeof(*sir_sme_dis_ind)); 1274 if (!sir_sme_dis_ind) 1275 return QDF_STATUS_E_FAILURE; 1276 1277 pe_debug("Prepare eWNI_SME_DISCONNECT_DONE_IND withretCode: %d", 1278 reason_code); 1279 1280 sir_sme_dis_ind->message_type = eWNI_SME_DISCONNECT_DONE_IND; 1281 sir_sme_dis_ind->length = sizeof(*sir_sme_dis_ind); 1282 sir_sme_dis_ind->session_id = session_id; 1283 if (peer_mac_addr) 1284 qdf_mem_copy(sir_sme_dis_ind->peer_mac, 1285 peer_mac_addr, ETH_ALEN); 1286 1287 /* 1288 * Instead of sending deauth reason code as 505 which is 1289 * internal value(eSIR_SME_LOST_LINK_WITH_PEER_RESULT_CODE) 1290 * Send reason code as zero to Supplicant 1291 */ 1292 if (reason_code == eSIR_SME_LOST_LINK_WITH_PEER_RESULT_CODE) 1293 sir_sme_dis_ind->reason_code = 0; 1294 else 1295 sir_sme_dis_ind->reason_code = reason_code; 1296 1297 *msg = (uint32_t *)sir_sme_dis_ind; 1298 1299 return QDF_STATUS_SUCCESS; 1300 } 1301 1302 void lim_send_sme_deauth_ntf(struct mac_context *mac, tSirMacAddr peerMacAddr, 1303 tSirResultCodes reasonCode, uint16_t deauthTrigger, 1304 uint16_t aid, uint8_t smesessionId) 1305 { 1306 uint8_t *pBuf; 1307 struct deauth_rsp *pSirSmeDeauthRsp; 1308 struct deauth_ind *pSirSmeDeauthInd = NULL; 1309 struct pe_session *pe_session; 1310 uint8_t sessionId; 1311 uint32_t *pMsg = NULL; 1312 QDF_STATUS status; 1313 enum QDF_OPMODE opmode; 1314 1315 pe_session = pe_find_session_by_bssid(mac, peerMacAddr, &sessionId); 1316 switch (deauthTrigger) { 1317 case eLIM_HOST_DEAUTH: 1318 /** 1319 * Deauthentication response to host triggered 1320 * deauthentication. 1321 */ 1322 pSirSmeDeauthRsp = qdf_mem_malloc(sizeof(*pSirSmeDeauthRsp)); 1323 if (!pSirSmeDeauthRsp) 1324 return; 1325 pe_debug("send eWNI_SME_DEAUTH_RSP with retCode: %d for " 1326 QDF_MAC_ADDR_FMT, 1327 reasonCode, QDF_MAC_ADDR_REF(peerMacAddr)); 1328 pSirSmeDeauthRsp->messageType = eWNI_SME_DEAUTH_RSP; 1329 pSirSmeDeauthRsp->length = sizeof(*pSirSmeDeauthRsp); 1330 pSirSmeDeauthRsp->status_code = reasonCode; 1331 pSirSmeDeauthRsp->sessionId = smesessionId; 1332 1333 pBuf = (uint8_t *) pSirSmeDeauthRsp->peer_macaddr.bytes; 1334 qdf_mem_copy(pBuf, peerMacAddr, sizeof(tSirMacAddr)); 1335 1336 #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM /* FEATURE_WLAN_DIAG_SUPPORT */ 1337 lim_diag_event_report(mac, WLAN_PE_DIAG_DEAUTH_RSP_EVENT, 1338 pe_session, 0, (uint16_t) reasonCode); 1339 #endif 1340 pMsg = (uint32_t *) pSirSmeDeauthRsp; 1341 1342 break; 1343 1344 case eLIM_PEER_ENTITY_DEAUTH: 1345 case eLIM_LINK_MONITORING_DEAUTH: 1346 status = lim_prepare_disconnect_done_ind(mac, &pMsg, 1347 smesessionId, reasonCode, 1348 &peerMacAddr[0]); 1349 if (!QDF_IS_STATUS_SUCCESS(status)) { 1350 pe_err("Failed to prepare message"); 1351 return; 1352 } 1353 break; 1354 default: 1355 /** 1356 * Deauthentication indication due to Deauthentication 1357 * frame reception from peer entity or due to 1358 * loss of link with peer entity. 1359 */ 1360 pSirSmeDeauthInd = qdf_mem_malloc(sizeof(*pSirSmeDeauthInd)); 1361 if (!pSirSmeDeauthInd) 1362 return; 1363 pe_debug("send eWNI_SME_DEAUTH_IND with retCode: %d for " 1364 QDF_MAC_ADDR_FMT, 1365 reasonCode, QDF_MAC_ADDR_REF(peerMacAddr)); 1366 pSirSmeDeauthInd->messageType = eWNI_SME_DEAUTH_IND; 1367 pSirSmeDeauthInd->length = sizeof(*pSirSmeDeauthInd); 1368 pSirSmeDeauthInd->reasonCode = REASON_UNSPEC_FAILURE; 1369 pSirSmeDeauthInd->vdev_id = smesessionId; 1370 pSirSmeDeauthInd->status_code = reasonCode; 1371 qdf_mem_copy(pSirSmeDeauthInd->bssid.bytes, pe_session->bssId, 1372 sizeof(tSirMacAddr)); 1373 qdf_mem_copy(pSirSmeDeauthInd->peer_macaddr.bytes, peerMacAddr, 1374 QDF_MAC_ADDR_SIZE); 1375 1376 #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM /* FEATURE_WLAN_DIAG_SUPPORT */ 1377 lim_diag_event_report(mac, WLAN_PE_DIAG_DEAUTH_IND_EVENT, 1378 pe_session, 0, (uint16_t) reasonCode); 1379 #endif /* FEATURE_WLAN_DIAG_SUPPORT */ 1380 pMsg = (uint32_t *) pSirSmeDeauthInd; 1381 1382 break; 1383 } 1384 1385 /*Delete the PE session created */ 1386 if (pe_session && LIM_IS_STA_ROLE(pe_session)) 1387 pe_delete_session(mac, pe_session); 1388 1389 opmode = wlan_get_opmode_from_vdev_id(mac->pdev, smesessionId); 1390 if ((opmode == QDF_STA_MODE || opmode == QDF_P2P_CLIENT_MODE) && 1391 pSirSmeDeauthInd && 1392 pSirSmeDeauthInd->messageType == eWNI_SME_DEAUTH_IND) { 1393 struct scheduler_msg msg = {0}; 1394 1395 msg.type = pSirSmeDeauthInd->messageType; 1396 msg.bodyptr = pSirSmeDeauthInd; 1397 return lim_send_sta_disconnect_ind(mac, &msg); 1398 } 1399 1400 lim_send_sme_disassoc_deauth_ntf(mac, QDF_STATUS_SUCCESS, 1401 (uint32_t *) pMsg); 1402 1403 } /*** end lim_send_sme_deauth_ntf() ***/ 1404 1405 void lim_send_sme_set_context_rsp(struct mac_context *mac, 1406 struct qdf_mac_addr peer_macaddr, 1407 uint16_t aid, 1408 tSirResultCodes resultCode, 1409 struct pe_session *pe_session, 1410 uint8_t smesessionId) 1411 { 1412 struct scheduler_msg mmhMsg = {0}; 1413 struct set_context_rsp *set_context_rsp; 1414 1415 set_context_rsp = qdf_mem_malloc(sizeof(*set_context_rsp)); 1416 if (!set_context_rsp) 1417 return; 1418 1419 set_context_rsp->messageType = eWNI_SME_SETCONTEXT_RSP; 1420 set_context_rsp->length = sizeof(*set_context_rsp); 1421 set_context_rsp->status_code = resultCode; 1422 1423 qdf_copy_macaddr(&set_context_rsp->peer_macaddr, &peer_macaddr); 1424 1425 set_context_rsp->sessionId = smesessionId; 1426 1427 mmhMsg.type = eWNI_SME_SETCONTEXT_RSP; 1428 mmhMsg.bodyptr = set_context_rsp; 1429 mmhMsg.bodyval = 0; 1430 if (!pe_session) { 1431 MTRACE(mac_trace(mac, TRACE_CODE_TX_SME_MSG, 1432 NO_SESSION, mmhMsg.type)); 1433 } else { 1434 MTRACE(mac_trace(mac, TRACE_CODE_TX_SME_MSG, 1435 pe_session->peSessionId, mmhMsg.type)); 1436 } 1437 1438 #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM /* FEATURE_WLAN_DIAG_SUPPORT */ 1439 lim_diag_event_report(mac, WLAN_PE_DIAG_SETCONTEXT_RSP_EVENT, 1440 pe_session, (uint16_t) resultCode, 0); 1441 #endif /* FEATURE_WLAN_DIAG_SUPPORT */ 1442 1443 mac->lim.sme_msg_callback(mac, &mmhMsg); 1444 } /*** end lim_send_sme_set_context_rsp() ***/ 1445 1446 void lim_send_sme_addts_rsp(struct mac_context *mac, 1447 uint8_t rspReqd, uint32_t status, 1448 struct pe_session *pe_session, 1449 struct mac_tspec_ie tspec, 1450 uint8_t smesessionId) 1451 { 1452 tpSirAddtsRsp rsp; 1453 struct scheduler_msg mmhMsg = {0}; 1454 1455 if (!rspReqd) 1456 return; 1457 1458 rsp = qdf_mem_malloc(sizeof(tSirAddtsRsp)); 1459 if (!rsp) 1460 return; 1461 1462 rsp->messageType = eWNI_SME_ADDTS_RSP; 1463 rsp->rc = status; 1464 rsp->rsp.status = (enum wlan_status_code)status; 1465 rsp->rsp.tspec = tspec; 1466 rsp->sessionId = smesessionId; 1467 1468 mmhMsg.type = eWNI_SME_ADDTS_RSP; 1469 mmhMsg.bodyptr = rsp; 1470 mmhMsg.bodyval = 0; 1471 if (!pe_session) { 1472 MTRACE(mac_trace(mac, TRACE_CODE_TX_SME_MSG, 1473 NO_SESSION, mmhMsg.type)); 1474 } else { 1475 MTRACE(mac_trace(mac, TRACE_CODE_TX_SME_MSG, 1476 pe_session->peSessionId, mmhMsg.type)); 1477 } 1478 #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM /* FEATURE_WLAN_DIAG_SUPPORT */ 1479 lim_diag_event_report(mac, WLAN_PE_DIAG_ADDTS_RSP_EVENT, pe_session, 0, 1480 0); 1481 #endif /* FEATURE_WLAN_DIAG_SUPPORT */ 1482 1483 lim_sys_process_mmh_msg_api(mac, &mmhMsg); 1484 return; 1485 } 1486 1487 void lim_send_sme_delts_rsp(struct mac_context *mac, tpSirDeltsReq delts, 1488 uint32_t status, struct pe_session *pe_session, 1489 uint8_t smesessionId) 1490 { 1491 tpSirDeltsRsp rsp; 1492 struct scheduler_msg mmhMsg = {0}; 1493 1494 pe_debug("SendSmeDeltsRsp aid: %d tsid: %d up: %d status: %d", 1495 delts->aid, 1496 delts->req.tsinfo.traffic.tsid, 1497 delts->req.tsinfo.traffic.userPrio, status); 1498 if (!delts->rspReqd) 1499 return; 1500 1501 rsp = qdf_mem_malloc(sizeof(tSirDeltsRsp)); 1502 if (!rsp) 1503 return; 1504 1505 if (pe_session) { 1506 1507 rsp->aid = delts->aid; 1508 qdf_copy_macaddr(&rsp->macaddr, &delts->macaddr); 1509 qdf_mem_copy((uint8_t *) &rsp->rsp, (uint8_t *) &delts->req, 1510 sizeof(struct delts_req_info)); 1511 } 1512 1513 rsp->messageType = eWNI_SME_DELTS_RSP; 1514 rsp->rc = status; 1515 rsp->sessionId = smesessionId; 1516 1517 mmhMsg.type = eWNI_SME_DELTS_RSP; 1518 mmhMsg.bodyptr = rsp; 1519 mmhMsg.bodyval = 0; 1520 if (!pe_session) { 1521 MTRACE(mac_trace(mac, TRACE_CODE_TX_SME_MSG, 1522 NO_SESSION, mmhMsg.type)); 1523 } else { 1524 MTRACE(mac_trace(mac, TRACE_CODE_TX_SME_MSG, 1525 pe_session->peSessionId, mmhMsg.type)); 1526 } 1527 #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM /* FEATURE_WLAN_DIAG_SUPPORT */ 1528 lim_diag_event_report(mac, WLAN_PE_DIAG_DELTS_RSP_EVENT, pe_session, 1529 (uint16_t) status, 0); 1530 #endif /* FEATURE_WLAN_DIAG_SUPPORT */ 1531 1532 lim_sys_process_mmh_msg_api(mac, &mmhMsg); 1533 } 1534 1535 void 1536 lim_send_sme_delts_ind(struct mac_context *mac, struct delts_req_info *delts, 1537 uint16_t aid, struct pe_session *pe_session) 1538 { 1539 tpSirDeltsRsp rsp; 1540 struct scheduler_msg mmhMsg = {0}; 1541 1542 pe_debug("SendSmeDeltsInd aid: %d tsid: %d up: %d", 1543 aid, delts->tsinfo.traffic.tsid, delts->tsinfo.traffic.userPrio); 1544 1545 rsp = qdf_mem_malloc(sizeof(tSirDeltsRsp)); 1546 if (!rsp) 1547 return; 1548 1549 rsp->messageType = eWNI_SME_DELTS_IND; 1550 rsp->rc = QDF_STATUS_SUCCESS; 1551 rsp->aid = aid; 1552 qdf_mem_copy((uint8_t *) &rsp->rsp, (uint8_t *) delts, sizeof(*delts)); 1553 rsp->sessionId = pe_session->smeSessionId; 1554 1555 mmhMsg.type = eWNI_SME_DELTS_IND; 1556 mmhMsg.bodyptr = rsp; 1557 mmhMsg.bodyval = 0; 1558 MTRACE(mac_trace_msg_tx(mac, pe_session->peSessionId, mmhMsg.type)); 1559 #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM /* FEATURE_WLAN_DIAG_SUPPORT */ 1560 lim_diag_event_report(mac, WLAN_PE_DIAG_DELTS_IND_EVENT, pe_session, 0, 1561 0); 1562 #endif /* FEATURE_WLAN_DIAG_SUPPORT */ 1563 1564 lim_sys_process_mmh_msg_api(mac, &mmhMsg); 1565 } 1566 1567 #ifdef FEATURE_WLAN_ESE 1568 /** 1569 * lim_send_sme_pe_ese_tsm_rsp() - send tsm response 1570 * @mac: Pointer to global mac structure 1571 * @pStats: Pointer to TSM Stats 1572 * 1573 * This function is called to send tsm stats response to HDD. 1574 * This function posts the result back to HDD. This is a response to 1575 * HDD's request to get tsm stats. 1576 * 1577 * Return: None 1578 */ 1579 void lim_send_sme_pe_ese_tsm_rsp(struct mac_context *mac, 1580 tAniGetTsmStatsRsp *pStats) 1581 { 1582 struct scheduler_msg mmhMsg = {0}; 1583 uint8_t sessionId; 1584 tAniGetTsmStatsRsp *pPeStats = (tAniGetTsmStatsRsp *) pStats; 1585 struct pe_session *pPeSessionEntry = NULL; 1586 1587 /* Get the Session Id based on Sta Id */ 1588 pPeSessionEntry = pe_find_session_by_bssid(mac, pPeStats->bssid.bytes, 1589 &sessionId); 1590 /* Fill the Session Id */ 1591 if (pPeSessionEntry) { 1592 /* Fill the Session Id */ 1593 pPeStats->sessionId = pPeSessionEntry->smeSessionId; 1594 } else { 1595 pe_err("Session not found for the Sta peer:" QDF_MAC_ADDR_FMT, 1596 QDF_MAC_ADDR_REF(pPeStats->bssid.bytes)); 1597 qdf_mem_free(pPeStats->tsmStatsReq); 1598 qdf_mem_free(pPeStats); 1599 return; 1600 } 1601 1602 pPeStats->msgType = eWNI_SME_GET_TSM_STATS_RSP; 1603 pPeStats->tsmMetrics.RoamingCount 1604 = pPeSessionEntry->eseContext.tsm.tsmMetrics.RoamingCount; 1605 pPeStats->tsmMetrics.RoamingDly 1606 = pPeSessionEntry->eseContext.tsm.tsmMetrics.RoamingDly; 1607 1608 mmhMsg.type = eWNI_SME_GET_TSM_STATS_RSP; 1609 mmhMsg.bodyptr = pStats; 1610 mmhMsg.bodyval = 0; 1611 MTRACE(mac_trace(mac, TRACE_CODE_TX_SME_MSG, sessionId, mmhMsg.type)); 1612 lim_sys_process_mmh_msg_api(mac, &mmhMsg); 1613 1614 return; 1615 } /*** end lim_send_sme_pe_ese_tsm_rsp() ***/ 1616 1617 #endif /* FEATURE_WLAN_ESE */ 1618 1619 /** 1620 * lim_process_csa_wbw_ie() - Process CSA Wide BW IE 1621 * @mac_ctx: pointer to global adapter context 1622 * @csa_params: pointer to CSA parameters 1623 * @chnl_switch_info:pointer to channel switch parameters 1624 * @session_entry: session pointer 1625 * 1626 * Return: None 1627 */ 1628 static QDF_STATUS lim_process_csa_wbw_ie(struct mac_context *mac_ctx, 1629 struct csa_offload_params *csa_params, 1630 tLimWiderBWChannelSwitchInfo *chnl_switch_info, 1631 struct pe_session *session_entry) 1632 { 1633 struct ch_params ch_params = {0}; 1634 enum phy_ch_width ap_new_ch_width; 1635 uint8_t center_freq_diff; 1636 uint32_t fw_vht_ch_wd = wma_get_vht_ch_width() + 1; 1637 uint32_t cent_freq1, cent_freq2; 1638 uint32_t csa_cent_freq, csa_cent_freq1 = 0, csa_cent_freq2 = 0; 1639 1640 ap_new_ch_width = csa_params->new_ch_width; 1641 1642 if (!csa_params->new_ch_freq_seg1 && !csa_params->new_ch_freq_seg2) 1643 return QDF_STATUS_E_INVAL; 1644 1645 csa_cent_freq = csa_params->csa_chan_freq; 1646 if (wlan_reg_is_6ghz_op_class(mac_ctx->pdev, 1647 csa_params->new_op_class)) { 1648 cent_freq1 = wlan_reg_chan_opclass_to_freq( 1649 csa_params->new_ch_freq_seg1, 1650 csa_params->new_op_class, false); 1651 cent_freq2 = wlan_reg_chan_opclass_to_freq( 1652 csa_params->new_ch_freq_seg2, 1653 csa_params->new_op_class, false); 1654 } else { 1655 cent_freq1 = wlan_reg_legacy_chan_to_freq(mac_ctx->pdev, 1656 csa_params->new_ch_freq_seg1); 1657 cent_freq2 = wlan_reg_legacy_chan_to_freq(mac_ctx->pdev, 1658 csa_params->new_ch_freq_seg2); 1659 } 1660 1661 switch (ap_new_ch_width) { 1662 case CH_WIDTH_80MHZ: 1663 csa_cent_freq1 = cent_freq1; 1664 if (csa_params->new_ch_freq_seg2) { 1665 center_freq_diff = abs(csa_params->new_ch_freq_seg2 - 1666 csa_params->new_ch_freq_seg1); 1667 if (center_freq_diff == CENTER_FREQ_DIFF_160MHz) { 1668 ap_new_ch_width = CH_WIDTH_160MHZ; 1669 csa_cent_freq1 = cent_freq2; 1670 csa_params->new_ch_freq_seg1 = 1671 csa_params->new_ch_freq_seg2; 1672 csa_params->new_ch_freq_seg2 = 0; 1673 } else if (center_freq_diff > CENTER_FREQ_DIFF_160MHz) { 1674 ap_new_ch_width = CH_WIDTH_80P80MHZ; 1675 csa_cent_freq2 = cent_freq2; 1676 } 1677 } 1678 break; 1679 case CH_WIDTH_80P80MHZ: 1680 csa_cent_freq1 = cent_freq1; 1681 csa_cent_freq2 = cent_freq2; 1682 break; 1683 case CH_WIDTH_160MHZ: 1684 csa_cent_freq1 = cent_freq1; 1685 break; 1686 default: 1687 pe_debug("CSA wide BW IE has ch_width %d", ap_new_ch_width); 1688 return QDF_STATUS_E_INVAL; 1689 } 1690 1691 /* Verify whether the bandwidth and channel segments are valid. */ 1692 switch (ap_new_ch_width) { 1693 case CH_WIDTH_80MHZ: 1694 if (abs(csa_cent_freq1 - csa_cent_freq) != 10 && 1695 abs(csa_cent_freq1 - csa_cent_freq) != 30) { 1696 pe_err("CSA WBW 80MHz has invalid seg0 freq %d", 1697 csa_cent_freq1); 1698 return QDF_STATUS_E_INVAL; 1699 } 1700 if (csa_cent_freq2) { 1701 pe_err("CSA WBW 80MHz has invalid seg1 freq %d", 1702 csa_cent_freq2); 1703 return QDF_STATUS_E_INVAL; 1704 } 1705 break; 1706 case CH_WIDTH_80P80MHZ: 1707 if (abs(csa_cent_freq1 - csa_cent_freq) != 10 && 1708 abs(csa_cent_freq1 - csa_cent_freq) != 30) { 1709 pe_err("CSA WBW 80MHz has invalid seg0 freq %d", 1710 csa_cent_freq1); 1711 return QDF_STATUS_E_INVAL; 1712 } 1713 if (!csa_cent_freq2) { 1714 pe_err("CSA WBW 80MHz has invalid seg1 freq %d", 1715 csa_cent_freq2); 1716 return QDF_STATUS_E_INVAL; 1717 } 1718 /* adjacent is not allowed -- that's a 160 MHz channel */ 1719 if (abs(csa_cent_freq1 - csa_cent_freq2) == 80) { 1720 pe_err("CSA WBW wrong bandwidth"); 1721 return QDF_STATUS_E_INVAL; 1722 } 1723 break; 1724 case CH_WIDTH_160MHZ: 1725 if (abs(csa_cent_freq1 - csa_cent_freq) != 70 && 1726 abs(csa_cent_freq1 - csa_cent_freq) != 50 && 1727 abs(csa_cent_freq1 - csa_cent_freq) != 30 && 1728 abs(csa_cent_freq1 - csa_cent_freq) != 10) { 1729 pr_err("CSA WBW 160MHz has invalid seg0 freq %d", 1730 csa_cent_freq1); 1731 return QDF_STATUS_E_INVAL; 1732 } 1733 if (csa_cent_freq2) { 1734 pe_err("CSA WBW 80MHz has invalid seg1 freq %d", 1735 csa_cent_freq2); 1736 return QDF_STATUS_E_INVAL; 1737 } 1738 break; 1739 default: 1740 pe_err("CSA wide BW IE has wrong ch_width %d", ap_new_ch_width); 1741 return QDF_STATUS_E_INVAL; 1742 } 1743 1744 if (ap_new_ch_width > fw_vht_ch_wd) { 1745 pe_debug("New BW is not supported, downgrade BW to %d", 1746 fw_vht_ch_wd); 1747 ap_new_ch_width = fw_vht_ch_wd; 1748 } 1749 ch_params.ch_width = ap_new_ch_width; 1750 wlan_reg_set_channel_params_for_pwrmode(mac_ctx->pdev, 1751 csa_params->csa_chan_freq, 1752 0, &ch_params, 1753 REG_CURRENT_PWR_MODE); 1754 ap_new_ch_width = ch_params.ch_width; 1755 csa_params->new_ch_freq_seg1 = ch_params.center_freq_seg0; 1756 csa_params->new_ch_freq_seg2 = ch_params.center_freq_seg1; 1757 1758 session_entry->gLimChannelSwitch.state = 1759 eLIM_CHANNEL_SWITCH_PRIMARY_AND_SECONDARY; 1760 1761 chnl_switch_info->newChanWidth = ap_new_ch_width; 1762 chnl_switch_info->newCenterChanFreq0 = csa_params->new_ch_freq_seg1; 1763 chnl_switch_info->newCenterChanFreq1 = csa_params->new_ch_freq_seg2; 1764 1765 return QDF_STATUS_SUCCESS; 1766 } 1767 1768 static bool lim_is_csa_channel_allowed(struct mac_context *mac_ctx, 1769 struct pe_session *session_entry, 1770 qdf_freq_t ch_freq1, 1771 struct csa_offload_params *csa_params) 1772 { 1773 bool is_allowed = true; 1774 u32 cnx_count = 0; 1775 enum QDF_OPMODE mode; 1776 qdf_freq_t csa_freq = csa_params->csa_chan_freq, sec_ch_2g_freq = 0; 1777 enum phy_ch_width new_ch_width = csa_params->new_ch_width; 1778 enum channel_state chan_state; 1779 1780 if (!session_entry->vdev || 1781 wlan_cm_is_vdev_disconnecting(session_entry->vdev) || 1782 wlan_cm_is_vdev_disconnected(session_entry->vdev)) { 1783 pe_warn("CSA is ignored, vdev %d is disconnecting/ed", 1784 session_entry->vdev_id); 1785 return false; 1786 } 1787 1788 /* 1789 * This is a temporary check and will be removed once ll_lt_sap CSA 1790 * support is added. 1791 */ 1792 if (policy_mgr_get_ll_lt_sap_freq(mac_ctx->psoc) == csa_freq) { 1793 pe_err("CSA not allowed on LL_LT_SAP freq %d", csa_freq); 1794 lim_tear_down_link_with_ap(mac_ctx, session_entry->peSessionId, 1795 REASON_CHANNEL_SWITCH_FAILED, 1796 eLIM_HOST_DISASSOC); 1797 return false; 1798 } 1799 1800 if (WLAN_REG_IS_24GHZ_CH_FREQ(csa_freq) && 1801 wlan_reg_get_bw_value(new_ch_width) > 20) { 1802 if (csa_params->new_ch_freq_seg1 == csa_params->channel + 2) 1803 sec_ch_2g_freq = csa_freq + HT40_SEC_OFFSET; 1804 else if (csa_params->new_ch_freq_seg1 == csa_params->channel - 2) 1805 sec_ch_2g_freq = csa_freq - HT40_SEC_OFFSET; 1806 } 1807 1808 chan_state = wlan_reg_get_bonded_channel_state_for_pwrmode( 1809 mac_ctx->pdev, 1810 csa_freq, new_ch_width, 1811 sec_ch_2g_freq, 1812 REG_CURRENT_PWR_MODE); 1813 if (chan_state == CHANNEL_STATE_INVALID || 1814 chan_state == CHANNEL_STATE_DISABLE) { 1815 pe_err("Invalid csa_freq %d ch_width %d ccfs0 %d ccfs1 %d sec_ch %d. Disconnect", 1816 csa_freq, new_ch_width, csa_params->new_ch_freq_seg1, 1817 csa_params->new_ch_freq_seg2, sec_ch_2g_freq); 1818 lim_tear_down_link_with_ap(mac_ctx, 1819 session_entry->peSessionId, 1820 REASON_CHANNEL_SWITCH_FAILED, 1821 eLIM_HOST_DISASSOC); 1822 return false; 1823 } 1824 1825 mode = wlan_vdev_mlme_get_opmode(session_entry->vdev); 1826 cnx_count = policy_mgr_get_connection_count(mac_ctx->psoc); 1827 if ((cnx_count > 1) && !policy_mgr_is_hw_dbs_capable(mac_ctx->psoc) && 1828 !policy_mgr_is_interband_mcc_supported(mac_ctx->psoc)) { 1829 is_allowed = wlan_reg_is_same_band_freqs(ch_freq1, csa_freq); 1830 } else if (cnx_count > 2) { 1831 is_allowed = 1832 policy_mgr_allow_concurrency_csa( 1833 mac_ctx->psoc, 1834 policy_mgr_qdf_opmode_to_pm_con_mode(mac_ctx->psoc, 1835 mode, 1836 session_entry->vdev_id), 1837 csa_freq, 1838 policy_mgr_get_bw(new_ch_width), 1839 session_entry->vdev_id, false, 1840 CSA_REASON_UNKNOWN); 1841 } 1842 1843 return is_allowed; 1844 } 1845 1846 #ifdef WLAN_FEATURE_11BE 1847 /** 1848 * lim_set_csa_chan_param_11be() - set csa chan params for 11be 1849 * @session: pointer to pe session 1850 * @csa_param: pointer to csa_offload_params 1851 * @ch_param: channel parameters to get 1852 * 1853 * Return: void 1854 */ 1855 static void lim_set_csa_chan_param_11be(struct pe_session *session, 1856 struct csa_offload_params *csa_param, 1857 struct ch_params *ch_param) 1858 { 1859 if (!session || !csa_param || !ch_param || !session->vdev) { 1860 pe_err("invalid input parameter"); 1861 return; 1862 } 1863 1864 if (csa_param->new_ch_width == CH_WIDTH_320MHZ && 1865 !session->eht_config.support_320mhz_6ghz) 1866 ch_param->ch_width = CH_WIDTH_160MHZ; 1867 1868 wlan_cm_sta_set_chan_param(session->vdev, 1869 csa_param->csa_chan_freq, 1870 csa_param->new_ch_width, 1871 csa_param->new_punct_bitmap, 1872 csa_param->new_ch_freq_seg1, 1873 csa_param->new_ch_freq_seg2, 1874 ch_param); 1875 } 1876 1877 /** 1878 * lim_set_chan_sw_puncture() - set puncture to channel switch info 1879 * @lim_ch_switch: pointer to tLimChannelSwitchInfo 1880 * @ch_param: pointer to ch_params 1881 * 1882 * Return: void 1883 */ 1884 static void lim_set_chan_sw_puncture(tLimChannelSwitchInfo *lim_ch_switch, 1885 struct ch_params *ch_param) 1886 { 1887 lim_ch_switch->puncture_bitmap = ch_param->reg_punc_bitmap; 1888 } 1889 1890 /** 1891 * lim_reset_csa_puncture() - reset puncture of channel switch 1892 * @lim_ch_switch: pointer to tLimChannelSwitchInfo 1893 * 1894 * Return: void 1895 */ 1896 static void lim_reset_csa_puncture(tLimChannelSwitchInfo *lim_ch_switch) 1897 { 1898 lim_ch_switch->puncture_bitmap = 0; 1899 } 1900 1901 /** 1902 * lim_is_puncture_same() - Check whether puncture changed 1903 * @lim_ch_switch: pointer to tLimChannelSwitchInfo 1904 * @session: pe session 1905 * 1906 * Return: bool, true: puncture changed 1907 */ 1908 static bool lim_is_puncture_same(tLimChannelSwitchInfo *lim_ch_switch, 1909 struct pe_session *session) 1910 { 1911 pe_debug("vdevid %d puncture, old: 0x%x, new: 0x%x", session->vdev_id, 1912 session->puncture_bitmap, 1913 lim_ch_switch->puncture_bitmap); 1914 return lim_ch_switch->puncture_bitmap == session->puncture_bitmap; 1915 } 1916 1917 static void update_csa_link_info(struct wlan_objmgr_vdev *vdev, 1918 uint8_t link_id, 1919 struct csa_offload_params *csa_params) 1920 { 1921 struct wlan_objmgr_pdev *pdev; 1922 uint8_t vdev_id = wlan_vdev_get_id(vdev); 1923 1924 pdev = wlan_vdev_get_pdev(vdev); 1925 if (!pdev) { 1926 pe_err("pdev is null"); 1927 return; 1928 } 1929 1930 mlo_mgr_update_csa_link_info(pdev, vdev->mlo_dev_ctx, 1931 csa_params, link_id); 1932 pe_debug("vdev_id: %d link id %d mlo csa sta param updated ", 1933 vdev_id, link_id); 1934 } 1935 1936 static bool 1937 lim_mlo_is_csa_allow(struct wlan_objmgr_vdev *vdev, uint16_t csa_freq) 1938 { 1939 return wlan_mlo_is_csa_allow(vdev, csa_freq); 1940 } 1941 1942 #else 1943 static void lim_set_csa_chan_param_11be(struct pe_session *session, 1944 struct csa_offload_params *csa_param, 1945 struct ch_params *ch_param) 1946 { 1947 } 1948 1949 static void lim_set_chan_sw_puncture(tLimChannelSwitchInfo *lim_ch_switch, 1950 struct ch_params *ch_param) 1951 { 1952 } 1953 1954 static void lim_reset_csa_puncture(tLimChannelSwitchInfo *lim_ch_switch) 1955 { 1956 } 1957 1958 static bool lim_is_puncture_same(tLimChannelSwitchInfo *lim_ch_switch, 1959 struct pe_session *session) 1960 { 1961 return true; 1962 } 1963 1964 static void update_csa_link_info(struct wlan_objmgr_vdev *vdev, 1965 uint8_t link_id, 1966 struct csa_offload_params *csa_params) 1967 { 1968 } 1969 1970 static bool 1971 lim_mlo_is_csa_allow(struct wlan_objmgr_vdev *vdev, uint16_t csa_freq) 1972 { 1973 return true; 1974 } 1975 #endif 1976 1977 /** 1978 * lim_sta_follow_csa() - Check if STA needs to follow CSA 1979 * @session_entry: Session pointer 1980 * @csa_params: Pointer to CSA params 1981 * @lim_ch_switch: Pointer to lim channel switch info 1982 * @ch_params: Channel params 1983 * 1984 * Return: True if CSA is required, else return false. 1985 */ 1986 static bool lim_sta_follow_csa(struct pe_session *session_entry, 1987 struct csa_offload_params *csa_params, 1988 tLimChannelSwitchInfo *lim_ch_switch, 1989 struct ch_params ch_params) 1990 { 1991 if (session_entry->curr_op_freq == csa_params->csa_chan_freq && 1992 session_entry->ch_width == ch_params.ch_width && 1993 lim_is_puncture_same(lim_ch_switch, session_entry)) { 1994 pe_debug("Ignore CSA, no change in ch, bw and puncture"); 1995 return false; 1996 } 1997 return true; 1998 } 1999 2000 void lim_handle_sta_csa_param(struct mac_context *mac_ctx, 2001 struct csa_offload_params *csa_params, 2002 bool send_status) 2003 { 2004 struct pe_session *session_entry; 2005 struct mlme_legacy_priv *mlme_priv; 2006 tpDphHashNode sta_ds = NULL; 2007 uint8_t session_id; 2008 uint16_t aid = 0; 2009 uint16_t chan_space = 0; 2010 struct ch_params ch_params = {0}; 2011 uint32_t channel_bonding_mode; 2012 uint8_t country_code[CDS_COUNTRY_CODE_LEN + 1]; 2013 tLimWiderBWChannelSwitchInfo *chnl_switch_info = NULL; 2014 tLimChannelSwitchInfo *lim_ch_switch = NULL; 2015 uint8_t link_id; 2016 2017 if (!csa_params) { 2018 pe_err("limMsgQ body ptr is NULL"); 2019 return; 2020 } 2021 2022 session_entry = 2023 pe_find_session_by_bssid(mac_ctx, 2024 csa_params->bssid.bytes, &session_id); 2025 if (!session_entry) { 2026 pe_err("Session does not exists for "QDF_MAC_ADDR_FMT, 2027 QDF_MAC_ADDR_REF(csa_params->bssid.bytes)); 2028 goto free; 2029 } 2030 sta_ds = dph_lookup_hash_entry(mac_ctx, session_entry->bssId, &aid, 2031 &session_entry->dph.dphHashTable); 2032 2033 if (!sta_ds) { 2034 pe_err("sta_ds does not exist"); 2035 goto send_event; 2036 } 2037 2038 if (!LIM_IS_STA_ROLE(session_entry)) { 2039 pe_debug("Invalid role to handle CSA"); 2040 goto send_event; 2041 } 2042 2043 lim_ch_switch = &session_entry->gLimChannelSwitch; 2044 ch_params.ch_width = csa_params->new_ch_width; 2045 2046 if (IS_DOT11_MODE_EHT(session_entry->dot11mode)) 2047 lim_set_csa_chan_param_11be(session_entry, csa_params, 2048 &ch_params); 2049 else 2050 wlan_reg_set_channel_params_for_pwrmode( 2051 mac_ctx->pdev, 2052 csa_params->csa_chan_freq, 2053 0, &ch_params, 2054 REG_CURRENT_PWR_MODE); 2055 lim_set_chan_sw_puncture(lim_ch_switch, &ch_params); 2056 2057 if (!lim_sta_follow_csa(session_entry, csa_params, 2058 lim_ch_switch, ch_params)) 2059 goto send_event; 2060 else 2061 qdf_mem_zero(&ch_params, sizeof(struct ch_params)); 2062 2063 if (!lim_is_csa_channel_allowed(mac_ctx, session_entry, 2064 session_entry->curr_op_freq, 2065 csa_params)) { 2066 pe_debug("Channel switch is not allowed"); 2067 goto send_event; 2068 } 2069 2070 if (!lim_mlo_is_csa_allow(session_entry->vdev, 2071 csa_params->csa_chan_freq)) { 2072 pe_debug("Channel switch for MLO vdev is not allowed"); 2073 goto send_event; 2074 } 2075 /* 2076 * on receiving channel switch announcement from AP, delete all 2077 * TDLS peers before leaving BSS and proceed for channel switch 2078 */ 2079 2080 lim_update_tdls_set_state_for_fw(session_entry, false); 2081 lim_delete_tdls_peers(mac_ctx, session_entry); 2082 2083 lim_ch_switch->switchMode = csa_params->switch_mode; 2084 /* timer already started by firmware, switch immediately */ 2085 lim_ch_switch->switchCount = 0; 2086 lim_ch_switch->primaryChannel = 2087 csa_params->channel; 2088 lim_ch_switch->sw_target_freq = 2089 csa_params->csa_chan_freq; 2090 lim_ch_switch->state = 2091 eLIM_CHANNEL_SWITCH_PRIMARY_ONLY; 2092 lim_ch_switch->ch_width = CH_WIDTH_20MHZ; 2093 lim_reset_csa_puncture(lim_ch_switch); 2094 2095 lim_ch_switch->sec_ch_offset = 2096 session_entry->htSecondaryChannelOffset; 2097 lim_ch_switch->ch_center_freq_seg0 = 0; 2098 lim_ch_switch->ch_center_freq_seg1 = 0; 2099 chnl_switch_info = 2100 &session_entry->gLimWiderBWChannelSwitch; 2101 2102 channel_bonding_mode = lim_get_cb_mode_for_freq(mac_ctx, session_entry, 2103 csa_params->csa_chan_freq); 2104 2105 pe_debug("Session %d vdev %d: vht: %d ht: %d he %d cbmode %d", 2106 session_entry->peSessionId, session_entry->vdev_id, 2107 session_entry->vhtCapability, 2108 session_entry->htSupportedChannelWidthSet, 2109 lim_is_session_he_capable(session_entry), 2110 channel_bonding_mode); 2111 2112 session_entry->htSupportedChannelWidthSet = false; 2113 wlan_reg_read_current_country(mac_ctx->psoc, country_code); 2114 if (!csa_params->ies_present_flag || 2115 (csa_params->ies_present_flag & MLME_CSWRAP_IE_EXT_V2_PRESENT)) { 2116 pe_debug("new freq: %u, width: %d", csa_params->csa_chan_freq, 2117 csa_params->new_ch_width); 2118 ch_params.ch_width = csa_params->new_ch_width; 2119 if (IS_DOT11_MODE_EHT(session_entry->dot11mode)) 2120 lim_set_csa_chan_param_11be(session_entry, csa_params, 2121 &ch_params); 2122 else 2123 wlan_reg_set_channel_params_for_pwrmode( 2124 mac_ctx->pdev, 2125 csa_params->csa_chan_freq, 2126 0, &ch_params, 2127 REG_CURRENT_PWR_MODE); 2128 pe_debug("idea width: %d, chn_seg0 %u chn_seg1 %u freq_seg0 %u freq_seg1 %u", 2129 ch_params.ch_width, ch_params.center_freq_seg0, 2130 ch_params.center_freq_seg1, ch_params.mhz_freq_seg0, 2131 ch_params.mhz_freq_seg1); 2132 2133 lim_ch_switch->sec_ch_offset = ch_params.sec_ch_offset; 2134 lim_ch_switch->ch_width = ch_params.ch_width; 2135 lim_ch_switch->ch_center_freq_seg0 = ch_params.center_freq_seg0; 2136 lim_ch_switch->ch_center_freq_seg1 = ch_params.center_freq_seg1; 2137 lim_set_chan_sw_puncture(lim_ch_switch, &ch_params); 2138 2139 if (ch_params.ch_width == CH_WIDTH_20MHZ) { 2140 lim_ch_switch->state = eLIM_CHANNEL_SWITCH_PRIMARY_ONLY; 2141 session_entry->htSupportedChannelWidthSet = false; 2142 } else { 2143 chnl_switch_info->newChanWidth = 2144 lim_ch_switch->ch_width; 2145 chnl_switch_info->newCenterChanFreq0 = 2146 lim_ch_switch->ch_center_freq_seg0; 2147 chnl_switch_info->newCenterChanFreq1 = 2148 lim_ch_switch->ch_center_freq_seg1; 2149 lim_ch_switch->state = 2150 eLIM_CHANNEL_SWITCH_PRIMARY_AND_SECONDARY; 2151 session_entry->htSupportedChannelWidthSet = true; 2152 } 2153 } else if (channel_bonding_mode && 2154 ((session_entry->vhtCapability && session_entry->htCapability) || 2155 lim_is_session_he_capable(session_entry))) { 2156 if ((csa_params->ies_present_flag & MLME_WBW_IE_PRESENT) && 2157 (QDF_STATUS_SUCCESS == lim_process_csa_wbw_ie( 2158 mac_ctx, csa_params, chnl_switch_info, 2159 session_entry))) { 2160 lim_ch_switch->sec_ch_offset = 2161 PHY_SINGLE_CHANNEL_CENTERED; 2162 if (chnl_switch_info->newChanWidth) { 2163 ch_params.ch_width = 2164 chnl_switch_info->newChanWidth; 2165 wlan_reg_set_channel_params_for_pwrmode( 2166 mac_ctx->pdev, 2167 csa_params->csa_chan_freq, 2168 0, &ch_params, 2169 REG_CURRENT_PWR_MODE); 2170 lim_ch_switch->sec_ch_offset = 2171 ch_params.sec_ch_offset; 2172 session_entry->htSupportedChannelWidthSet = 2173 true; 2174 } 2175 } else if (csa_params->ies_present_flag 2176 & MLME_XCSA_IE_PRESENT) { 2177 uint32_t fw_vht_ch_wd = wma_get_vht_ch_width(); 2178 2179 if (wlan_reg_is_6ghz_op_class 2180 (mac_ctx->pdev, csa_params->new_op_class)) { 2181 chan_space = wlan_reg_get_op_class_width 2182 (mac_ctx->pdev, 2183 csa_params->new_op_class, true); 2184 } else { 2185 chan_space = 2186 wlan_reg_dmn_get_chanwidth_from_opclass_auto( 2187 country_code, 2188 csa_params->channel, 2189 csa_params->new_op_class); 2190 } 2191 if (chan_space >= 160 && fw_vht_ch_wd < 2192 WNI_CFG_VHT_CHANNEL_WIDTH_160MHZ) 2193 chan_space = 80; 2194 lim_ch_switch->state = 2195 eLIM_CHANNEL_SWITCH_PRIMARY_AND_SECONDARY; 2196 if (chan_space == 160) { 2197 chnl_switch_info->newChanWidth = 2198 CH_WIDTH_160MHZ; 2199 } else if (chan_space == 80) { 2200 chnl_switch_info->newChanWidth = 2201 CH_WIDTH_80MHZ; 2202 session_entry->htSupportedChannelWidthSet = 2203 true; 2204 } else if (chan_space == 40) { 2205 chnl_switch_info->newChanWidth = 2206 CH_WIDTH_40MHZ; 2207 session_entry->htSupportedChannelWidthSet = 2208 true; 2209 } else { 2210 chnl_switch_info->newChanWidth = 2211 CH_WIDTH_20MHZ; 2212 lim_ch_switch->state = 2213 eLIM_CHANNEL_SWITCH_PRIMARY_ONLY; 2214 } 2215 2216 ch_params.ch_width = 2217 chnl_switch_info->newChanWidth; 2218 wlan_reg_set_channel_params_for_pwrmode( 2219 mac_ctx->pdev, csa_params->csa_chan_freq, 0, 2220 &ch_params, REG_CURRENT_PWR_MODE); 2221 chnl_switch_info->newCenterChanFreq0 = 2222 ch_params.center_freq_seg0; 2223 /* 2224 * This is not applicable for 20/40/80 MHz. 2225 * Only used when we support 80+80 MHz operation. 2226 * In case of 80+80 MHz, this parameter indicates 2227 * center channel frequency index of 80 MHz 2228 * channel offrequency segment 1. 2229 */ 2230 chnl_switch_info->newCenterChanFreq1 = 2231 ch_params.center_freq_seg1; 2232 lim_ch_switch->sec_ch_offset = 2233 ch_params.sec_ch_offset; 2234 } else { 2235 lim_ch_switch->state = 2236 eLIM_CHANNEL_SWITCH_PRIMARY_AND_SECONDARY; 2237 ch_params.ch_width = CH_WIDTH_40MHZ; 2238 wlan_reg_set_channel_params_for_pwrmode( 2239 mac_ctx->pdev, 2240 csa_params->csa_chan_freq, 2241 0, &ch_params, 2242 REG_CURRENT_PWR_MODE); 2243 lim_ch_switch->sec_ch_offset = 2244 ch_params.sec_ch_offset; 2245 chnl_switch_info->newChanWidth = CH_WIDTH_40MHZ; 2246 chnl_switch_info->newCenterChanFreq0 = 2247 ch_params.center_freq_seg0; 2248 chnl_switch_info->newCenterChanFreq1 = 0; 2249 session_entry->htSupportedChannelWidthSet = true; 2250 } 2251 lim_ch_switch->ch_center_freq_seg0 = 2252 chnl_switch_info->newCenterChanFreq0; 2253 lim_ch_switch->ch_center_freq_seg1 = 2254 chnl_switch_info->newCenterChanFreq1; 2255 lim_ch_switch->ch_width = 2256 chnl_switch_info->newChanWidth; 2257 2258 } else if (channel_bonding_mode && session_entry->htCapability) { 2259 if (csa_params->ies_present_flag 2260 & MLME_XCSA_IE_PRESENT) { 2261 chan_space = 2262 wlan_reg_dmn_get_chanwidth_from_opclass_auto( 2263 country_code, 2264 csa_params->channel, 2265 csa_params->new_op_class); 2266 lim_ch_switch->state = 2267 eLIM_CHANNEL_SWITCH_PRIMARY_AND_SECONDARY; 2268 if (chan_space == 40) { 2269 lim_ch_switch->ch_width = 2270 CH_WIDTH_40MHZ; 2271 chnl_switch_info->newChanWidth = 2272 CH_WIDTH_40MHZ; 2273 ch_params.ch_width = 2274 chnl_switch_info->newChanWidth; 2275 wlan_reg_set_channel_params_for_pwrmode( 2276 mac_ctx->pdev, 2277 csa_params->csa_chan_freq, 2278 0, &ch_params, 2279 REG_CURRENT_PWR_MODE); 2280 lim_ch_switch->ch_center_freq_seg0 = 2281 ch_params.center_freq_seg0; 2282 lim_ch_switch->sec_ch_offset = 2283 ch_params.sec_ch_offset; 2284 session_entry->htSupportedChannelWidthSet = 2285 true; 2286 } else { 2287 lim_ch_switch->ch_width = 2288 CH_WIDTH_20MHZ; 2289 chnl_switch_info->newChanWidth = 2290 CH_WIDTH_20MHZ; 2291 lim_ch_switch->state = 2292 eLIM_CHANNEL_SWITCH_PRIMARY_ONLY; 2293 lim_ch_switch->sec_ch_offset = 2294 PHY_SINGLE_CHANNEL_CENTERED; 2295 } 2296 } else { 2297 lim_ch_switch->ch_width = 2298 CH_WIDTH_40MHZ; 2299 lim_ch_switch->state = 2300 eLIM_CHANNEL_SWITCH_PRIMARY_AND_SECONDARY; 2301 ch_params.ch_width = CH_WIDTH_40MHZ; 2302 wlan_reg_set_channel_params_for_pwrmode( 2303 mac_ctx->pdev, 2304 csa_params->csa_chan_freq, 2305 0, &ch_params, 2306 REG_CURRENT_PWR_MODE); 2307 lim_ch_switch->ch_center_freq_seg0 = 2308 ch_params.center_freq_seg0; 2309 lim_ch_switch->sec_ch_offset = 2310 ch_params.sec_ch_offset; 2311 session_entry->htSupportedChannelWidthSet = true; 2312 } 2313 } 2314 2315 lim_cp_stats_cstats_log_csa_evt(session_entry, CSTATS_DIR_RX, 2316 lim_ch_switch->sw_target_freq, 2317 lim_ch_switch->ch_width, 2318 lim_ch_switch->switchMode); 2319 2320 pe_debug("new ch %d: freq %d width: %d freq0 %d freq1 %d ht width %d, current freq %d: bw %d", 2321 lim_ch_switch->primaryChannel, lim_ch_switch->sw_target_freq, 2322 lim_ch_switch->ch_width, lim_ch_switch->ch_center_freq_seg0, 2323 lim_ch_switch->ch_center_freq_seg1, 2324 lim_ch_switch->sec_ch_offset, session_entry->curr_op_freq, 2325 session_entry->ch_width); 2326 2327 if (!lim_sta_follow_csa(session_entry, csa_params, 2328 lim_ch_switch, ch_params)) 2329 goto send_event; 2330 2331 if (wlan_vdev_mlme_is_mlo_vdev(session_entry->vdev)) { 2332 link_id = wlan_vdev_get_link_id(session_entry->vdev); 2333 update_csa_link_info(session_entry->vdev, link_id, csa_params); 2334 } else { 2335 mlme_priv = wlan_vdev_mlme_get_ext_hdl(session_entry->vdev); 2336 if (!mlme_priv) 2337 return; 2338 mlme_priv->connect_info.assoc_chan_info.assoc_ch_width = 2339 csa_params->new_ch_width; 2340 } 2341 2342 if (WLAN_REG_IS_24GHZ_CH_FREQ(csa_params->csa_chan_freq) && 2343 session_entry->dot11mode == MLME_DOT11_MODE_11A) 2344 session_entry->dot11mode = MLME_DOT11_MODE_11G; 2345 else if (!WLAN_REG_IS_24GHZ_CH_FREQ(csa_params->csa_chan_freq) && 2346 ((session_entry->dot11mode == MLME_DOT11_MODE_11G) || 2347 (session_entry->dot11mode == MLME_DOT11_MODE_11G_ONLY))) 2348 session_entry->dot11mode = MLME_DOT11_MODE_11A; 2349 2350 /* Send RSO Stop to FW before triggering the vdev restart for CSA */ 2351 if (mac_ctx->lim.stop_roaming_callback) 2352 mac_ctx->lim.stop_roaming_callback(MAC_HANDLE(mac_ctx), 2353 session_entry->smeSessionId, 2354 REASON_VDEV_RESTART_FROM_HOST, 2355 RSO_CHANNEL_SWITCH); 2356 2357 if (mlo_is_any_link_disconnecting(session_entry->vdev)) { 2358 pe_info_rl("Ignore CSA, vdev is in not in conncted state"); 2359 goto send_event; 2360 } 2361 2362 lim_prepare_for11h_channel_switch(mac_ctx, session_entry); 2363 2364 lim_flush_bssid(mac_ctx, session_entry->bssId); 2365 2366 #ifdef FEATURE_WLAN_DIAG_SUPPORT 2367 lim_diag_event_report(mac_ctx, 2368 WLAN_PE_DIAG_SWITCH_CHL_IND_EVENT, session_entry, 2369 QDF_STATUS_SUCCESS, QDF_STATUS_SUCCESS); 2370 #endif 2371 free: 2372 qdf_mem_free(csa_params); 2373 return; 2374 send_event: 2375 if (send_status) 2376 wlan_mlme_send_csa_event_status_ind(session_entry->vdev, 0); 2377 qdf_mem_free(csa_params); 2378 } 2379 2380 void lim_handle_csa_offload_msg(struct mac_context *mac_ctx, 2381 struct scheduler_msg *msg) 2382 { 2383 struct pe_session *session; 2384 struct csa_offload_params *csa_params = 2385 (struct csa_offload_params *)(msg->bodyptr); 2386 uint8_t session_id; 2387 2388 if (!csa_params) { 2389 pe_err("limMsgQ body ptr is NULL"); 2390 return; 2391 } 2392 2393 session = pe_find_session_by_bssid( 2394 mac_ctx, csa_params->bssid.bytes, &session_id); 2395 if (!session) { 2396 pe_err("Session does not exists for " QDF_MAC_ADDR_FMT, 2397 QDF_MAC_ADDR_REF(csa_params->bssid.bytes)); 2398 qdf_mem_free(csa_params); 2399 return; 2400 } 2401 if (wlan_vdev_mlme_is_mlo_vdev(session->vdev) && 2402 mlo_is_sta_csa_param_handled(session->vdev, csa_params)) { 2403 pe_debug("vdev_id: %d, csa param is already handled. return", 2404 session_id); 2405 qdf_mem_free(csa_params); 2406 return; 2407 } 2408 lim_handle_sta_csa_param(mac_ctx, csa_params, true); 2409 } 2410 2411 #ifdef WLAN_FEATURE_11BE_MLO 2412 void lim_handle_mlo_sta_csa_param(struct wlan_objmgr_vdev *vdev, 2413 struct csa_offload_params *csa_params) 2414 { 2415 struct mac_context *mac; 2416 struct csa_offload_params *tmp_csa_params; 2417 2418 mac = cds_get_context(QDF_MODULE_ID_PE); 2419 if (!mac) { 2420 pe_err("mac ctx is null"); 2421 return; 2422 } 2423 2424 tmp_csa_params = qdf_mem_malloc(sizeof(*tmp_csa_params)); 2425 if (!tmp_csa_params) { 2426 pe_err("tmp_csa_params allocation fails"); 2427 return; 2428 } 2429 2430 qdf_mem_copy(tmp_csa_params, csa_params, sizeof(*tmp_csa_params)); 2431 2432 lim_handle_sta_csa_param(mac, tmp_csa_params, false); 2433 } 2434 #endif 2435 2436 /*-------------------------------------------------------------------------- 2437 \brief pe_delete_session() - Handle the Delete BSS Response from HAL. 2438 2439 \param mac - pointer to global adapter context 2440 \param sessionId - Message pointer. 2441 2442 \sa 2443 --------------------------------------------------------------------------*/ 2444 2445 void lim_handle_delete_bss_rsp(struct mac_context *mac, 2446 struct del_bss_resp *del_bss_rsp) 2447 { 2448 struct pe_session *pe_session; 2449 2450 pe_session = 2451 pe_find_session_by_vdev_id_and_state(mac, 2452 del_bss_rsp->vdev_id, 2453 eLIM_MLM_WT_DEL_BSS_RSP_STATE); 2454 if (!pe_session) { 2455 qdf_mem_free(del_bss_rsp); 2456 return; 2457 } 2458 2459 /* 2460 * During DEL BSS handling, the PE Session will be deleted, but it is 2461 * better to clear this flag if the session is hanging around due 2462 * to some error conditions so that the next DEL_BSS request does 2463 * not take the HO_FAIL path 2464 */ 2465 pe_session->process_ho_fail = false; 2466 if (LIM_IS_UNKNOWN_ROLE(pe_session)) 2467 lim_process_sme_del_bss_rsp(mac, pe_session); 2468 else if (LIM_IS_NDI_ROLE(pe_session)) 2469 lim_ndi_del_bss_rsp(mac, del_bss_rsp, pe_session); 2470 else 2471 lim_process_mlm_del_bss_rsp(mac, del_bss_rsp, pe_session); 2472 2473 qdf_mem_free(del_bss_rsp); 2474 } 2475 2476 /** ----------------------------------------------------------------- 2477 \brief lim_send_sme_aggr_qos_rsp() - sends SME FT AGGR QOS RSP 2478 \ This function sends a eWNI_SME_FT_AGGR_QOS_RSP to SME. 2479 \ SME only looks at rc and tspec field. 2480 \param mac - global mac structure 2481 \param rspReqd - is SmeAddTsRsp required 2482 \param status - status code of eWNI_SME_FT_AGGR_QOS_RSP 2483 \return tspec 2484 \sa 2485 ----------------------------------------------------------------- */ 2486 void 2487 lim_send_sme_aggr_qos_rsp(struct mac_context *mac, tpSirAggrQosRsp aggrQosRsp, 2488 uint8_t smesessionId) 2489 { 2490 struct scheduler_msg mmhMsg = {0}; 2491 2492 mmhMsg.type = eWNI_SME_FT_AGGR_QOS_RSP; 2493 mmhMsg.bodyptr = aggrQosRsp; 2494 mmhMsg.bodyval = 0; 2495 MTRACE(mac_trace(mac, TRACE_CODE_TX_SME_MSG, 2496 smesessionId, mmhMsg.type)); 2497 lim_sys_process_mmh_msg_api(mac, &mmhMsg); 2498 2499 return; 2500 } 2501 2502 void lim_send_sme_max_assoc_exceeded_ntf(struct mac_context *mac, tSirMacAddr peerMacAddr, 2503 uint8_t smesessionId) 2504 { 2505 struct scheduler_msg mmhMsg = {0}; 2506 tSmeMaxAssocInd *pSmeMaxAssocInd; 2507 2508 pSmeMaxAssocInd = qdf_mem_malloc(sizeof(tSmeMaxAssocInd)); 2509 if (!pSmeMaxAssocInd) 2510 return; 2511 qdf_mem_copy((uint8_t *) pSmeMaxAssocInd->peer_mac.bytes, 2512 (uint8_t *) peerMacAddr, QDF_MAC_ADDR_SIZE); 2513 pSmeMaxAssocInd->mesgType = eWNI_SME_MAX_ASSOC_EXCEEDED; 2514 pSmeMaxAssocInd->mesgLen = sizeof(tSmeMaxAssocInd); 2515 pSmeMaxAssocInd->sessionId = smesessionId; 2516 mmhMsg.type = pSmeMaxAssocInd->mesgType; 2517 mmhMsg.bodyptr = pSmeMaxAssocInd; 2518 pe_debug("msgType: %s peerMacAddr "QDF_MAC_ADDR_FMT "sme session id %d", 2519 "eWNI_SME_MAX_ASSOC_EXCEEDED", QDF_MAC_ADDR_REF(peerMacAddr), 2520 pSmeMaxAssocInd->sessionId); 2521 MTRACE(mac_trace(mac, TRACE_CODE_TX_SME_MSG, 2522 smesessionId, mmhMsg.type)); 2523 lim_sys_process_mmh_msg_api(mac, &mmhMsg); 2524 2525 return; 2526 } 2527 2528 /** ----------------------------------------------------------------- 2529 \brief lim_send_sme_ap_channel_switch_resp() - sends 2530 eWNI_SME_CHANNEL_CHANGE_RSP 2531 After receiving WMA_SWITCH_CHANNEL_RSP indication this 2532 function sends a eWNI_SME_CHANNEL_CHANGE_RSP to SME to notify 2533 that the Channel change has been done to the specified target 2534 channel in the Channel change request 2535 \param mac - global mac structure 2536 \param pe_session - session info 2537 \param pChnlParams - Channel switch params 2538 --------------------------------------------------------------------*/ 2539 void 2540 lim_send_sme_ap_channel_switch_resp(struct mac_context *mac, 2541 struct pe_session *pe_session, 2542 struct vdev_start_response *rsp) 2543 { 2544 struct scheduler_msg mmhMsg = {0}; 2545 struct sSirChanChangeResponse *chan_change_rsp; 2546 bool is_ch_dfs = false; 2547 enum phy_ch_width ch_width; 2548 uint32_t ch_cfreq1 = 0; 2549 enum reg_wifi_band band; 2550 2551 qdf_runtime_pm_allow_suspend(&pe_session->ap_ecsa_runtime_lock); 2552 qdf_wake_lock_release(&pe_session->ap_ecsa_wakelock, 0); 2553 2554 chan_change_rsp = 2555 qdf_mem_malloc(sizeof(struct sSirChanChangeResponse)); 2556 if (!chan_change_rsp) 2557 return; 2558 2559 chan_change_rsp->new_op_freq = pe_session->curr_op_freq; 2560 chan_change_rsp->channelChangeStatus = rsp->status; 2561 /* 2562 * Pass the sme sessionID to SME instead 2563 * PE session ID. 2564 */ 2565 chan_change_rsp->sessionId = rsp->vdev_id; 2566 2567 mmhMsg.type = eWNI_SME_CHANNEL_CHANGE_RSP; 2568 mmhMsg.bodyptr = (void *)chan_change_rsp; 2569 mmhMsg.bodyval = 0; 2570 lim_sys_process_mmh_msg_api(mac, &mmhMsg); 2571 2572 if (QDF_IS_STATUS_ERROR(rsp->status)) { 2573 pe_err("failed to change sap freq to %u", 2574 pe_session->curr_op_freq); 2575 return; 2576 } 2577 2578 /* 2579 * We should start beacon transmission only if the new 2580 * channel after channel change is Non-DFS. For a DFS 2581 * channel, PE will receive an explicit request from 2582 * upper layers to start the beacon transmission . 2583 */ 2584 ch_width = pe_session->ch_width; 2585 band = wlan_reg_freq_to_band(pe_session->curr_op_freq); 2586 if (pe_session->ch_center_freq_seg1) 2587 ch_cfreq1 = wlan_reg_chan_band_to_freq( 2588 mac->pdev, 2589 pe_session->ch_center_freq_seg1, 2590 BIT(band)); 2591 2592 if (ch_width == CH_WIDTH_160MHZ) { 2593 struct ch_params ch_params = {0}; 2594 2595 if (IS_DOT11_MODE_EHT(pe_session->dot11mode)) 2596 wlan_reg_set_create_punc_bitmap(&ch_params, true); 2597 ch_params.ch_width = ch_width; 2598 if (wlan_reg_get_5g_bonded_channel_state_for_pwrmode(mac->pdev, 2599 pe_session->curr_op_freq, 2600 &ch_params, 2601 REG_CURRENT_PWR_MODE) == 2602 CHANNEL_STATE_DFS) 2603 is_ch_dfs = true; 2604 } else if (ch_width == CH_WIDTH_80P80MHZ) { 2605 if (wlan_reg_get_channel_state_for_pwrmode( 2606 mac->pdev, 2607 pe_session->curr_op_freq, 2608 REG_CURRENT_PWR_MODE) == 2609 CHANNEL_STATE_DFS || 2610 wlan_reg_get_channel_state_for_pwrmode( 2611 mac->pdev, 2612 ch_cfreq1, 2613 REG_CURRENT_PWR_MODE) == 2614 CHANNEL_STATE_DFS) 2615 is_ch_dfs = true; 2616 } else { 2617 /* Indoor channels are also marked DFS, therefore 2618 * check if the channel has REGULATORY_CHAN_RADAR 2619 * channel flag to identify if the channel is DFS 2620 */ 2621 if (wlan_reg_is_dfs_for_freq(mac->pdev, 2622 pe_session->curr_op_freq)) 2623 is_ch_dfs = true; 2624 } 2625 if (WLAN_REG_IS_6GHZ_CHAN_FREQ(pe_session->curr_op_freq)) 2626 is_ch_dfs = false; 2627 2628 if (is_ch_dfs) { 2629 lim_sap_move_to_cac_wait_state(pe_session); 2630 2631 } else { 2632 lim_apply_configuration(mac, pe_session); 2633 lim_send_beacon(mac, pe_session); 2634 lim_obss_send_detection_cfg(mac, pe_session, true); 2635 } 2636 return; 2637 } 2638 2639 #ifdef WLAN_FEATURE_11AX_BSS_COLOR 2640 /** 2641 * lim_send_bss_color_change_ie_update() - update bss color change IE in 2642 * beacon template 2643 * 2644 * @mac_ctx: pointer to global adapter context 2645 * @session: session pointer 2646 * 2647 * Return: none 2648 */ 2649 static void 2650 lim_send_bss_color_change_ie_update(struct mac_context *mac_ctx, 2651 struct pe_session *session) 2652 { 2653 /* Update the beacon template and send to FW */ 2654 if (sch_set_fixed_beacon_fields(mac_ctx, session) != QDF_STATUS_SUCCESS) { 2655 pe_err("Unable to set BSS color change IE in beacon"); 2656 return; 2657 } 2658 2659 /* Send update beacon template message */ 2660 lim_send_beacon_ind(mac_ctx, session, REASON_COLOR_CHANGE); 2661 pe_debug("Updated BSS color change countdown = %d", 2662 session->he_bss_color_change.countdown); 2663 } 2664 2665 #ifdef WLAN_FEATURE_SR 2666 static void 2667 lim_update_spatial_reuse(struct pe_session *session) 2668 { 2669 struct wlan_objmgr_psoc *psoc; 2670 uint32_t conc_vdev_id; 2671 uint8_t mac_id, sr_ctrl, non_srg_pd_max_offset; 2672 uint8_t vdev_id = session->vdev_id; 2673 2674 sr_ctrl = wlan_vdev_mlme_get_sr_ctrl(session->vdev); 2675 non_srg_pd_max_offset = 2676 wlan_vdev_mlme_get_non_srg_pd_offset(session->vdev); 2677 if (non_srg_pd_max_offset && sr_ctrl && 2678 wlan_vdev_mlme_get_he_spr_enabled(session->vdev)) { 2679 psoc = wlan_vdev_get_psoc(session->vdev); 2680 policy_mgr_get_mac_id_by_session_id(psoc, 2681 vdev_id, 2682 &mac_id); 2683 conc_vdev_id = policy_mgr_get_conc_vdev_on_same_mac(psoc, 2684 vdev_id, 2685 mac_id); 2686 if (conc_vdev_id == WLAN_INVALID_VDEV_ID || 2687 policy_mgr_sr_same_mac_conc_enabled(psoc)) { 2688 wlan_vdev_mlme_set_sr_disable_due_conc(session->vdev, 2689 false); 2690 wlan_spatial_reuse_config_set(session->vdev, sr_ctrl, 2691 non_srg_pd_max_offset); 2692 wlan_spatial_reuse_osif_event(session->vdev, 2693 SR_OPERATION_RESUME, 2694 SR_REASON_CODE_CONCURRENCY); 2695 } else { 2696 wlan_vdev_mlme_set_sr_disable_due_conc(session->vdev, 2697 true); 2698 wlan_spatial_reuse_config_set(session->vdev, sr_ctrl, 2699 NON_SR_PD_THRESHOLD_DISABLED); 2700 wlan_spatial_reuse_osif_event(session->vdev, 2701 SR_OPERATION_SUSPEND, 2702 SR_REASON_CODE_CONCURRENCY); 2703 } 2704 } 2705 } 2706 #else 2707 static void 2708 lim_update_spatial_reuse(struct pe_session *session) 2709 { 2710 } 2711 #endif 2712 2713 static void 2714 lim_handle_bss_color_change_ie(struct mac_context *mac_ctx, 2715 struct pe_session *session) 2716 { 2717 tUpdateBeaconParams beacon_params; 2718 2719 /* handle bss color change IE */ 2720 if (LIM_IS_AP_ROLE(session) && 2721 session->he_op.bss_col_disabled && 2722 session->he_bss_color_change.new_color) { 2723 pe_debug("countdown: %d, new_color: %d", 2724 session->he_bss_color_change.countdown, 2725 session->he_bss_color_change.new_color); 2726 if (session->he_bss_color_change.countdown > 0) { 2727 session->he_bss_color_change.countdown--; 2728 } else { 2729 session->bss_color_changing = 0; 2730 /* 2731 * On OBSS color collision detection, spatial reuse 2732 * gets disabled. Enable spatial reuse if it was 2733 * enabled during AP start 2734 */ 2735 lim_update_spatial_reuse(session); 2736 qdf_mem_zero(&beacon_params, sizeof(beacon_params)); 2737 session->he_op.bss_col_disabled = 0; 2738 session->he_op.bss_color = 2739 session->he_bss_color_change.new_color; 2740 session->he_bss_color_change.new_color = 0; 2741 beacon_params.paramChangeBitmap |= 2742 PARAM_BSS_COLOR_CHANGED; 2743 beacon_params.bss_color_disabled = 0; 2744 beacon_params.bss_color = session->he_op.bss_color; 2745 lim_send_beacon_params(mac_ctx, 2746 &beacon_params, 2747 session); 2748 lim_send_obss_color_collision_cfg( 2749 mac_ctx, session, 2750 OBSS_COLOR_COLLISION_DETECTION); 2751 wma_allow_suspend_after_obss_color_change( 2752 session->vdev); 2753 } 2754 lim_send_bss_color_change_ie_update(mac_ctx, session); 2755 } 2756 } 2757 2758 #else 2759 static void 2760 lim_handle_bss_color_change_ie(struct mac_context *mac_ctx, 2761 struct pe_session *session) 2762 { 2763 } 2764 #endif 2765 2766 void 2767 lim_process_beacon_tx_success_ind(struct mac_context *mac_ctx, uint16_t msgType, 2768 void *event) 2769 { 2770 struct pe_session *session; 2771 struct wlan_objmgr_vdev *vdev; 2772 bool csa_tx_offload, is_sap_go_moved_before_sta = false; 2773 tpSirFirstBeaconTxCompleteInd bcn_ind = 2774 (tSirFirstBeaconTxCompleteInd *) event; 2775 2776 session = pe_find_session_by_vdev_id(mac_ctx, bcn_ind->bss_idx); 2777 if (!session) { 2778 pe_err("Session Does not exist for given session id"); 2779 return; 2780 } 2781 2782 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(mac_ctx->psoc, 2783 session->vdev_id, 2784 WLAN_LEGACY_MAC_ID); 2785 if (vdev) { 2786 is_sap_go_moved_before_sta = 2787 wlan_vdev_mlme_is_sap_go_move_before_sta(vdev); 2788 wlan_vdev_mlme_set_sap_go_move_before_sta(vdev, false); 2789 wlan_objmgr_vdev_release_ref(vdev, WLAN_LEGACY_MAC_ID); 2790 } 2791 pe_debug("role: %d swIe: %d opIe: %d switch cnt:%d Is SAP / GO Moved before STA: %d", 2792 GET_LIM_SYSTEM_ROLE(session), 2793 session->dfsIncludeChanSwIe, 2794 session->gLimOperatingMode.present, 2795 session->gLimChannelSwitch.switchCount, 2796 is_sap_go_moved_before_sta); 2797 2798 if (!LIM_IS_AP_ROLE(session)) 2799 return; 2800 csa_tx_offload = wlan_psoc_nif_fw_ext_cap_get(mac_ctx->psoc, 2801 WLAN_SOC_CEXT_CSA_TX_OFFLOAD); 2802 if ((session->dfsIncludeChanSwIe && !csa_tx_offload && 2803 ((session->gLimChannelSwitch.switchCount == 2804 mac_ctx->sap.SapDfsInfo.sap_ch_switch_beacon_cnt) || 2805 (session->gLimChannelSwitch.switchCount == 1) || 2806 is_sap_go_moved_before_sta)) || 2807 session->bw_update_include_ch_sw_ie) 2808 lim_process_ap_ecsa_timeout(session); 2809 2810 if (session->gLimOperatingMode.present) 2811 /* Done with nss update */ 2812 session->gLimOperatingMode.present = 0; 2813 2814 lim_handle_bss_color_change_ie(mac_ctx, session); 2815 2816 return; 2817 } 2818 2819 void lim_nss_or_ch_width_update_rsp(struct mac_context *mac_ctx, 2820 uint8_t vdev_id, QDF_STATUS status, 2821 enum sir_bcn_update_reason reason) 2822 { 2823 struct scheduler_msg msg = {0}; 2824 struct sir_bcn_update_rsp *rsp; 2825 QDF_STATUS qdf_status = QDF_STATUS_E_INVAL; 2826 2827 rsp = qdf_mem_malloc(sizeof(*rsp)); 2828 if (rsp) { 2829 rsp->vdev_id = vdev_id; 2830 rsp->status = status; 2831 rsp->reason = reason; 2832 } 2833 2834 if (reason == REASON_NSS_UPDATE) 2835 msg.type = eWNI_SME_NSS_UPDATE_RSP; 2836 else if (reason == REASON_CH_WIDTH_UPDATE) 2837 msg.type = eWNI_SME_SAP_CH_WIDTH_UPDATE_RSP; 2838 else 2839 goto done; 2840 2841 msg.bodyptr = rsp; 2842 msg.bodyval = 0; 2843 qdf_status = scheduler_post_message(QDF_MODULE_ID_PE, QDF_MODULE_ID_SME, 2844 QDF_MODULE_ID_SME, &msg); 2845 done: 2846 if (QDF_IS_STATUS_ERROR(qdf_status)) 2847 qdf_mem_free(rsp); 2848 } 2849