1 /* 2 * Copyright (c) 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 any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 /* 19 * DOC: wlan_cm_roam_logging.c 20 * 21 * Implementation for the connectivity and roam logging api. 22 */ 23 #include "wlan_connectivity_logging.h" 24 #include "wlan_cm_api.h" 25 #include "wlan_mlme_main.h" 26 #include "wlan_mlo_mgr_sta.h" 27 #include "wlan_mlme_api.h" 28 #include "cdp_txrx_ctrl.h" 29 #include "wlan_mlo_mgr_peer.h" 30 #include "wlan_scan_api.h" 31 32 #ifdef WLAN_FEATURE_CONNECTIVITY_LOGGING 33 static struct wlan_connectivity_log_buf_data global_cl; 34 35 static void 36 wlan_connectivity_logging_register_callbacks( 37 struct wlan_cl_osif_cbks *osif_cbks, 38 void *osif_cb_context) 39 { 40 global_cl.osif_cbks.wlan_connectivity_log_send_to_usr = 41 osif_cbks->wlan_connectivity_log_send_to_usr; 42 global_cl.osif_cb_context = osif_cb_context; 43 } 44 45 void wlan_connectivity_logging_start(struct wlan_objmgr_psoc *psoc, 46 struct wlan_cl_osif_cbks *osif_cbks, 47 void *osif_cb_context) 48 { 49 global_cl.head = qdf_mem_valloc(sizeof(*global_cl.head) * 50 WLAN_MAX_LOG_RECORDS); 51 if (!global_cl.head) { 52 QDF_BUG(0); 53 return; 54 } 55 56 global_cl.psoc = psoc; 57 global_cl.write_idx = 0; 58 global_cl.read_idx = 0; 59 60 qdf_atomic_init(&global_cl.dropped_msgs); 61 qdf_spinlock_create(&global_cl.write_ptr_lock); 62 63 global_cl.read_ptr = global_cl.head; 64 global_cl.write_ptr = global_cl.head; 65 global_cl.max_records = WLAN_MAX_LOG_RECORDS; 66 67 wlan_connectivity_logging_register_callbacks(osif_cbks, 68 osif_cb_context); 69 qdf_atomic_set(&global_cl.is_active, 1); 70 } 71 72 void wlan_connectivity_logging_stop(void) 73 { 74 if (!qdf_atomic_read(&global_cl.is_active)) 75 return; 76 77 qdf_spin_lock_bh(&global_cl.write_ptr_lock); 78 79 global_cl.psoc = NULL; 80 global_cl.osif_cb_context = NULL; 81 global_cl.osif_cbks.wlan_connectivity_log_send_to_usr = NULL; 82 83 qdf_atomic_set(&global_cl.is_active, 0); 84 global_cl.read_ptr = NULL; 85 global_cl.write_ptr = NULL; 86 global_cl.read_idx = 0; 87 global_cl.write_idx = 0; 88 89 qdf_mem_vfree(global_cl.head); 90 global_cl.head = NULL; 91 qdf_spin_unlock_bh(&global_cl.write_ptr_lock); 92 qdf_spinlock_destroy(&global_cl.write_ptr_lock); 93 } 94 #endif 95 96 #if defined(WLAN_FEATURE_ROAM_OFFLOAD) && \ 97 defined(WLAN_FEATURE_11BE_MLO) 98 static void 99 wlan_clear_ml_vdev_sae_auth_logs(struct wlan_objmgr_psoc *psoc, 100 struct wlan_objmgr_vdev *vdev) 101 { 102 struct wlan_mlo_dev_context *mlo_dev_ctx; 103 struct wlan_objmgr_vdev *link_vdev; 104 struct mlme_legacy_priv *mlme_priv; 105 uint8_t i, link_vdev_id; 106 107 mlo_dev_ctx = vdev->mlo_dev_ctx; 108 if (!mlo_dev_ctx) { 109 logging_err_rl("mlo_dev ctx is NULL for vdev:%d", 110 wlan_vdev_get_id(vdev)); 111 return; 112 } 113 114 for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) { 115 if (!mlo_dev_ctx->wlan_vdev_list[i]) 116 continue; 117 118 link_vdev_id = 119 wlan_vdev_get_id(mlo_dev_ctx->wlan_vdev_list[i]); 120 link_vdev = mlo_dev_ctx->wlan_vdev_list[i]; 121 122 mlme_priv = wlan_vdev_mlme_get_ext_hdl(link_vdev); 123 if (!mlme_priv) { 124 logging_err_rl("vdev:%d legacy private object is NULL", 125 link_vdev_id); 126 return; 127 } 128 129 logging_debug("vdev:%d clear sae auth logs cache", 130 link_vdev_id); 131 qdf_mem_zero(mlme_priv->auth_log, sizeof(mlme_priv->auth_log)); 132 } 133 } 134 #else 135 static inline void 136 wlan_clear_ml_vdev_sae_auth_logs(struct wlan_objmgr_psoc *psoc, 137 struct wlan_objmgr_vdev *vdev) 138 {} 139 #endif 140 141 #ifdef WLAN_FEATURE_ROAM_OFFLOAD 142 void wlan_clear_sae_auth_logs_cache(struct wlan_objmgr_psoc *psoc, 143 uint8_t vdev_id) 144 { 145 struct wlan_objmgr_vdev *vdev; 146 struct mlme_legacy_priv *mlme_priv; 147 148 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id, 149 WLAN_MLME_OBJMGR_ID); 150 if (!vdev) { 151 logging_err_rl("Invalid vdev:%d", vdev_id); 152 return; 153 } 154 155 if (wlan_vdev_mlme_is_mlo_vdev(vdev)) { 156 wlan_clear_ml_vdev_sae_auth_logs(psoc, vdev); 157 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_OBJMGR_ID); 158 return; 159 } 160 161 mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev); 162 if (!mlme_priv) { 163 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_OBJMGR_ID); 164 logging_err_rl("vdev legacy private object is NULL"); 165 return; 166 } 167 168 logging_debug("vdev:%d clear sae auth logs cache", vdev_id); 169 qdf_mem_zero(mlme_priv->auth_log, sizeof(mlme_priv->auth_log)); 170 171 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_OBJMGR_ID); 172 } 173 #endif 174 175 #if defined(WLAN_FEATURE_ROAM_OFFLOAD) && defined(CONNECTIVITY_DIAG_EVENT) 176 QDF_STATUS wlan_print_cached_sae_auth_logs(struct wlan_objmgr_psoc *psoc, 177 struct qdf_mac_addr *bssid, 178 uint8_t vdev_id) 179 { 180 uint8_t i, j; 181 struct wlan_objmgr_vdev *vdev; 182 struct mlme_legacy_priv *mlme_priv; 183 184 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id, 185 WLAN_MLME_OBJMGR_ID); 186 if (!vdev) { 187 logging_err_rl("Invalid vdev:%d", vdev_id); 188 return QDF_STATUS_E_FAILURE; 189 } 190 191 if (wlan_vdev_mlme_get_opmode(vdev) != QDF_STA_MODE) { 192 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_OBJMGR_ID); 193 return QDF_STATUS_E_FAILURE; 194 } 195 196 mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev); 197 if (!mlme_priv) { 198 logging_err_rl("vdev legacy private object is NULL"); 199 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_OBJMGR_ID); 200 return QDF_STATUS_E_FAILURE; 201 } 202 203 /* 204 * Get the index of matching bssid and queue all the records for 205 * that bssid 206 */ 207 for (i = 0; i < MAX_ROAM_CANDIDATE_AP; i++) { 208 if (!mlme_priv->auth_log[i][0].diag_cmn.ktime_us) 209 continue; 210 211 if (qdf_is_macaddr_equal(bssid, 212 (struct qdf_mac_addr *)mlme_priv->auth_log[i][0].diag_cmn.bssid)) 213 break; 214 } 215 216 /* 217 * No matching bssid found in cached log records. 218 * So return from here. 219 */ 220 if (i >= MAX_ROAM_CANDIDATE_AP) { 221 logging_debug("No cached SAE auth logs"); 222 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_OBJMGR_ID); 223 return QDF_STATUS_E_FAILURE; 224 } 225 226 for (j = 0; j < WLAN_ROAM_MAX_CACHED_AUTH_FRAMES; j++) { 227 if (!mlme_priv->auth_log[i][j].diag_cmn.ktime_us) 228 continue; 229 230 WLAN_HOST_DIAG_EVENT_REPORT(&mlme_priv->auth_log[i][j], 231 EVENT_WLAN_MGMT); 232 qdf_mem_zero(&mlme_priv->auth_log[i][j], 233 sizeof(struct wlan_diag_packet_info)); 234 } 235 236 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_OBJMGR_ID); 237 238 return QDF_STATUS_SUCCESS; 239 } 240 241 bool wlan_is_log_record_present_for_bssid(struct wlan_objmgr_psoc *psoc, 242 struct qdf_mac_addr *bssid, 243 uint8_t vdev_id) 244 { 245 struct wlan_diag_packet_info *pkt_info; 246 struct wlan_objmgr_vdev *vdev; 247 struct mlme_legacy_priv *mlme_priv; 248 int i; 249 250 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id, 251 WLAN_MLME_OBJMGR_ID); 252 if (!vdev) { 253 logging_err_rl("Invalid vdev:%d", vdev_id); 254 return false; 255 } 256 257 mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev); 258 if (!mlme_priv) { 259 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_OBJMGR_ID); 260 logging_err_rl("vdev legacy private object is NULL"); 261 return false; 262 } 263 264 for (i = 0; i < MAX_ROAM_CANDIDATE_AP; i++) { 265 pkt_info = &mlme_priv->auth_log[i][0]; 266 if (!pkt_info->diag_cmn.ktime_us) 267 continue; 268 269 if (qdf_is_macaddr_equal(bssid, 270 (struct qdf_mac_addr *)pkt_info->diag_cmn.bssid)) { 271 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_OBJMGR_ID); 272 return true; 273 } 274 } 275 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_OBJMGR_ID); 276 277 return false; 278 } 279 280 #ifdef WLAN_FEATURE_11BE_MLO 281 bool 282 wlan_is_sae_auth_log_present_for_bssid(struct wlan_objmgr_psoc *psoc, 283 struct qdf_mac_addr *bssid, 284 uint8_t *vdev_id) 285 { 286 struct wlan_objmgr_vdev *vdev; 287 struct wlan_mlo_dev_context *mlo_dev_ctx; 288 uint8_t i, link_vdev_id; 289 290 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, *vdev_id, 291 WLAN_MLME_OBJMGR_ID); 292 if (!vdev) { 293 logging_err_rl("Invalid vdev:%d", *vdev_id); 294 return false; 295 } 296 297 if (!wlan_vdev_mlme_is_mlo_vdev(vdev)) { 298 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_OBJMGR_ID); 299 return wlan_is_log_record_present_for_bssid(psoc, bssid, 300 *vdev_id); 301 } 302 303 mlo_dev_ctx = vdev->mlo_dev_ctx; 304 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_OBJMGR_ID); 305 306 if (!mlo_dev_ctx) { 307 logging_err_rl("mlo_dev ctx is NULL for vdev:%d", *vdev_id); 308 return wlan_is_log_record_present_for_bssid(psoc, bssid, 309 *vdev_id); 310 } 311 312 for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) { 313 if (!mlo_dev_ctx->wlan_vdev_list[i]) 314 continue; 315 316 link_vdev_id = wlan_vdev_get_id(mlo_dev_ctx->wlan_vdev_list[i]); 317 if (wlan_is_log_record_present_for_bssid(psoc, bssid, 318 link_vdev_id)) { 319 *vdev_id = link_vdev_id; 320 return true; 321 } 322 } 323 324 return false; 325 } 326 #else 327 bool 328 wlan_is_sae_auth_log_present_for_bssid(struct wlan_objmgr_psoc *psoc, 329 struct qdf_mac_addr *bssid, 330 uint8_t *vdev_id) 331 { 332 return wlan_is_log_record_present_for_bssid(psoc, bssid, *vdev_id); 333 } 334 #endif 335 336 /** 337 * wlan_add_sae_log_record_to_available_slot() - Add a new log record into the 338 * cache for the queue. 339 * @psoc: objmgr psoc object 340 * @vdev: objmgr vdev object 341 * @pkt_info: Log packet record pointer 342 * 343 * Return: QDF_STATUS 344 */ 345 static QDF_STATUS 346 wlan_add_sae_log_record_to_available_slot(struct wlan_objmgr_psoc *psoc, 347 struct wlan_objmgr_vdev *vdev, 348 struct wlan_diag_packet_info *pkt_info) 349 { 350 struct mlme_legacy_priv *mlme_priv; 351 uint8_t i, j; 352 uint8_t vdev_id = wlan_vdev_get_id(vdev); 353 bool is_entry_exist = 354 wlan_is_log_record_present_for_bssid(psoc, 355 (struct qdf_mac_addr *)pkt_info->diag_cmn.bssid, 356 vdev_id); 357 358 mlme_priv = wlan_vdev_mlme_get_ext_hdl(vdev); 359 if (!mlme_priv) { 360 logging_err_rl("vdev:%d legacy private object is NULL", 361 vdev_id); 362 return QDF_STATUS_E_FAILURE; 363 } 364 365 for (i = 0; i < MAX_ROAM_CANDIDATE_AP; i++) { 366 if (is_entry_exist && 367 mlme_priv->auth_log[i][0].diag_cmn.ktime_us && 368 qdf_is_macaddr_equal((struct qdf_mac_addr *)pkt_info->diag_cmn.bssid, 369 (struct qdf_mac_addr *)mlme_priv->auth_log[i][0].diag_cmn.bssid)) { 370 /* 371 * Frames for given bssid already exists store the new 372 * frame in corresponding array in empty slot 373 */ 374 for (j = 0; j < WLAN_ROAM_MAX_CACHED_AUTH_FRAMES; j++) { 375 if (mlme_priv->auth_log[i][j].diag_cmn.ktime_us) 376 continue; 377 378 logging_debug("vdev:%d added at [i][j]:[%d][%d]", 379 vdev_id, i, j); 380 mlme_priv->auth_log[i][j] = *pkt_info; 381 break; 382 } 383 384 } else if (!is_entry_exist && 385 !mlme_priv->auth_log[i][0].diag_cmn.ktime_us) { 386 /* 387 * For given record, there is no existing bssid 388 * so add the entry at first available slot 389 */ 390 logging_debug("vdev:%d added entry at [i][j]:[%d][%d]", 391 vdev_id, i, 0); 392 mlme_priv->auth_log[i][0] = *pkt_info; 393 break; 394 } 395 } 396 397 return QDF_STATUS_SUCCESS; 398 } 399 400 static void 401 wlan_cache_connectivity_log(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id, 402 struct wlan_diag_packet_info *pkt_info) 403 { 404 struct wlan_objmgr_vdev *vdev; 405 406 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id, 407 WLAN_MLME_OBJMGR_ID); 408 if (!vdev) { 409 logging_err_rl("Invalid vdev:%d", vdev_id); 410 return; 411 } 412 413 wlan_add_sae_log_record_to_available_slot(psoc, vdev, pkt_info); 414 415 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_OBJMGR_ID); 416 } 417 #endif 418 419 #define WLAN_SAE_AUTH_ALGO_NUMBER 3 420 #ifdef CONNECTIVITY_DIAG_EVENT 421 422 #ifdef WLAN_FEATURE_11BE_MLO 423 void 424 wlan_connectivity_t2lm_req_resp_event(struct wlan_objmgr_vdev *vdev, 425 uint8_t token, 426 enum wlan_t2lm_resp_frm_type t2lm_status, 427 enum qdf_dp_tx_rx_status tx_status, 428 qdf_freq_t freq, 429 bool is_rx, uint8_t subtype) 430 { 431 WLAN_HOST_DIAG_EVENT_DEF(wlan_diag_event, 432 struct wlan_diag_mlo_t2lm_req_resp); 433 434 wlan_diag_event.diag_cmn.vdev_id = wlan_vdev_get_id(vdev); 435 wlan_diag_event.diag_cmn.ktime_us = qdf_ktime_to_us(qdf_ktime_get()); 436 wlan_diag_event.diag_cmn.timestamp_us = qdf_get_time_of_the_day_us(); 437 438 wlan_diag_event.version = DIAG_MLO_T2LM_REQ_RESP_VERSION; 439 440 wlan_diag_event.token = token; 441 wlan_diag_event.subtype = subtype; 442 443 wlan_diag_event.status = t2lm_status; 444 wlan_diag_event.tx_status = wlan_get_diag_tx_status(tx_status); 445 wlan_diag_event.is_rx = is_rx; 446 447 wlan_diag_event.band = wlan_convert_freq_to_diag_band(freq); 448 449 WLAN_HOST_DIAG_EVENT_REPORT(&wlan_diag_event, 450 EVENT_WLAN_MLO_T2LM_REQ_RESP); 451 } 452 453 void 454 wlan_connectivity_mlo_reconfig_event(struct wlan_objmgr_vdev *vdev) 455 { 456 struct mlo_link_info *link_info = NULL; 457 struct wlan_channel *chan_info = NULL; 458 uint8_t link_id; 459 460 WLAN_HOST_DIAG_EVENT_DEF(wlan_diag_event, 461 struct wlan_diag_mlo_reconfig); 462 463 wlan_diag_event.diag_cmn.ktime_us = qdf_ktime_to_us(qdf_ktime_get()); 464 wlan_diag_event.diag_cmn.timestamp_us = qdf_get_time_of_the_day_us(); 465 wlan_diag_event.version = DIAG_MLO_RECONFIG_VERSION; 466 467 link_id = wlan_vdev_get_link_id(vdev); 468 wlan_diag_event.mlo_cmn_info.link_id = link_id; 469 470 if (!vdev->mlo_dev_ctx) 471 return; 472 473 link_info = mlo_mgr_get_ap_link_by_link_id(vdev->mlo_dev_ctx, link_id); 474 if (!link_info) { 475 mlme_err("linl: %d Link info not found", link_id); 476 return; 477 } 478 chan_info = link_info->link_chan_info; 479 if (!chan_info) { 480 mlme_err("link: %d Chan info not found", link_id); 481 return; 482 } 483 484 wlan_diag_event.mlo_cmn_info.band = 485 wlan_convert_freq_to_diag_band(chan_info->ch_freq); 486 487 WLAN_HOST_DIAG_EVENT_REPORT(&wlan_diag_event, EVENT_WLAN_MLO_RECONFIG); 488 } 489 490 static QDF_STATUS 491 wlan_populate_link_addr(struct wlan_objmgr_vdev *vdev, 492 struct wlan_diag_sta_info *wlan_diag_event) 493 { 494 uint i = 0; 495 struct mlo_link_switch_context *link_ctx = vdev->mlo_dev_ctx->link_ctx; 496 struct wlan_channel *link_chan_info; 497 498 if (!link_ctx) 499 return QDF_STATUS_E_FAILURE; 500 501 for (i = 0; i < WLAN_MAX_ML_BSS_LINKS; i++) { 502 link_chan_info = link_ctx->links_info[i].link_chan_info; 503 504 if (wlan_reg_is_24ghz_ch_freq( 505 (qdf_freq_t)link_chan_info->ch_freq)) { 506 qdf_mem_copy(wlan_diag_event->mac_2g, 507 link_ctx->links_info[i].link_addr.bytes, 508 QDF_MAC_ADDR_SIZE); 509 } else if (wlan_reg_is_5ghz_ch_freq( 510 (qdf_freq_t)link_chan_info->ch_freq)) { 511 qdf_mem_copy(wlan_diag_event->mac_5g, 512 link_ctx->links_info[i].link_addr.bytes, 513 QDF_MAC_ADDR_SIZE); 514 } else if (wlan_reg_is_6ghz_chan_freq( 515 link_chan_info->ch_freq)) { 516 qdf_mem_copy(wlan_diag_event->mac_6g, 517 link_ctx->links_info[i].link_addr.bytes, 518 QDF_MAC_ADDR_SIZE); 519 } 520 } 521 522 return QDF_STATUS_SUCCESS; 523 } 524 525 static uint8_t 526 wlan_populate_band_bitmap(struct mlo_link_switch_context *link_ctx) 527 { 528 uint8_t i, band_bitmap = 0, band; 529 struct wlan_channel *link_chan_info; 530 531 for (i = 0; i < WLAN_MAX_ML_BSS_LINKS; i++) { 532 link_chan_info = link_ctx->links_info[i].link_chan_info; 533 534 band = wlan_reg_freq_to_band((qdf_freq_t) 535 link_chan_info->ch_freq); 536 537 band_bitmap |= BIT(band); 538 } 539 540 return band_bitmap; 541 } 542 543 QDF_STATUS 544 wlan_populate_mlo_mgmt_event_param(struct wlan_objmgr_vdev *vdev, 545 struct wlan_diag_packet_info *data, 546 enum wlan_main_tag tag) 547 { 548 struct mlo_link_switch_context *link_ctx; 549 struct qdf_mac_addr peer_mac, peer_mld_mac; 550 QDF_STATUS status = QDF_STATUS_SUCCESS; 551 552 if (!mlo_is_mld_sta(vdev)) 553 return status; 554 555 if (wlan_vdev_mlme_is_mlo_link_vdev(vdev)) 556 return QDF_STATUS_E_INVAL; 557 558 status = wlan_vdev_get_bss_peer_mac(vdev, &peer_mac); 559 if (QDF_IS_STATUS_ERROR(status)) { 560 logging_err("vdev: %d bss peer not found", 561 wlan_vdev_get_id(vdev)); 562 return status; 563 } 564 565 qdf_mem_copy(data->diag_cmn.bssid, peer_mac.bytes, QDF_MAC_ADDR_SIZE); 566 567 status = wlan_vdev_get_bss_peer_mld_mac(vdev, &peer_mld_mac); 568 if (QDF_IS_STATUS_ERROR(status)) { 569 logging_err("vdev: %d failed to get mld mac address of peer", 570 wlan_vdev_get_id(vdev)); 571 return status; 572 } 573 574 qdf_mem_copy(data->mld_addr, peer_mld_mac.bytes, QDF_MAC_ADDR_SIZE); 575 576 if (tag != WLAN_ASSOC_REQ && tag != WLAN_REASSOC_REQ) 577 return status; 578 579 link_ctx = vdev->mlo_dev_ctx->link_ctx; 580 if (!link_ctx) { 581 logging_debug("vdev: %d link_ctx not found", 582 wlan_vdev_get_id(vdev)); 583 return QDF_STATUS_E_INVAL; 584 } 585 586 data->supported_links = wlan_populate_band_bitmap(link_ctx); 587 588 return status; 589 } 590 591 QDF_STATUS 592 wlan_populate_roam_mld_log_param(struct wlan_objmgr_vdev *vdev, 593 struct wlan_diag_packet_info *data, 594 enum wlan_main_tag tag) 595 { 596 struct wlan_objmgr_pdev *pdev; 597 QDF_STATUS status = QDF_STATUS_SUCCESS; 598 599 if (!mlo_is_mld_sta(vdev)) 600 return status; 601 602 pdev = wlan_vdev_get_pdev(vdev); 603 if (!pdev) 604 return QDF_STATUS_E_INVAL; 605 606 status = wlan_scan_get_mld_addr_by_link_addr( 607 pdev, (struct qdf_mac_addr *)data->diag_cmn.bssid, 608 (struct qdf_mac_addr *)data->mld_addr); 609 if (QDF_IS_STATUS_ERROR(status)) 610 logging_err_rl("vdev:%d Not able to fetch MLD addr for link addr: " QDF_MAC_ADDR_FMT, 611 wlan_vdev_get_id(vdev), 612 QDF_MAC_ADDR_REF(data->diag_cmn.bssid)); 613 614 return status; 615 } 616 617 enum wlan_diag_wifi_band 618 wlan_convert_freq_to_diag_band(uint16_t ch_freq) 619 { 620 enum reg_wifi_band band; 621 622 band = wlan_reg_freq_to_band((qdf_freq_t)ch_freq); 623 624 switch (band) { 625 case REG_BAND_2G: 626 return WLAN_24GHZ_BAND; 627 case REG_BAND_5G: 628 return WLAN_5GHZ_BAND; 629 case REG_BAND_6G: 630 return WLAN_6GHZ_BAND; 631 default: 632 return WLAN_INVALID_BAND; 633 } 634 } 635 636 #define REJECTED_LINK_STATUS 1 637 638 void 639 wlan_connectivity_mlo_setup_event(struct wlan_objmgr_vdev *vdev) 640 { 641 uint i = 0; 642 struct mlo_link_switch_context *link_ctx = NULL; 643 struct wlan_channel *chan_info; 644 uint8_t num_links = 0; 645 646 WLAN_HOST_DIAG_EVENT_DEF(wlan_diag_event, 647 struct wlan_diag_mlo_setup); 648 649 if (!mlo_is_mld_sta(vdev)) 650 return; 651 652 qdf_mem_zero(&wlan_diag_event, sizeof(struct wlan_diag_mlo_setup)); 653 654 wlan_diag_event.diag_cmn.ktime_us = qdf_ktime_to_us(qdf_ktime_get()); 655 wlan_diag_event.diag_cmn.timestamp_us = qdf_get_time_of_the_day_us(); 656 wlan_diag_event.version = DIAG_MLO_SETUP_VERSION_V2; 657 658 if (!vdev->mlo_dev_ctx) { 659 logging_err("vdev: %d MLO dev ctx not found", 660 wlan_vdev_get_id(vdev)); 661 return; 662 } 663 664 link_ctx = vdev->mlo_dev_ctx->link_ctx; 665 if (!link_ctx) { 666 logging_err("vdev: %d mlo link ctx not found", 667 wlan_vdev_get_id(vdev)); 668 return; 669 } 670 671 for (i = 0; i < WLAN_MAX_ML_BSS_LINKS; i++) { 672 if (link_ctx->links_info[i].link_id == WLAN_INVALID_LINK_ID) 673 continue; 674 675 chan_info = link_ctx->links_info[i].link_chan_info; 676 if (!chan_info) { 677 logging_debug("link %d: chan_info not found", 678 link_ctx->links_info[i].link_id); 679 continue; 680 } 681 682 wlan_diag_event.mlo_cmn_info[num_links].link_id = 683 link_ctx->links_info[i].link_id; 684 wlan_diag_event.mlo_cmn_info[num_links].vdev_id = 685 link_ctx->links_info[i].vdev_id; 686 687 qdf_mem_copy(wlan_diag_event.mlo_cmn_info[num_links].link_addr, 688 link_ctx->links_info[i].ap_link_addr.bytes, 689 QDF_MAC_ADDR_SIZE); 690 691 wlan_diag_event.mlo_cmn_info[num_links].band = 692 wlan_convert_freq_to_diag_band(chan_info->ch_freq); 693 694 if (wlan_diag_event.mlo_cmn_info[num_links].band == 695 WLAN_INVALID_BAND) 696 wlan_diag_event.mlo_cmn_info[i].status = 697 REJECTED_LINK_STATUS; 698 699 num_links++; 700 } 701 702 wlan_diag_event.num_links = num_links; 703 704 WLAN_HOST_DIAG_EVENT_REPORT(&wlan_diag_event, EVENT_WLAN_MLO_SETUP); 705 } 706 707 #define IS_LINK_SET(link_bitmap, link_id) ((link_bitmap) & (BIT(link_id))) 708 #define DEFAULT_TID_MAP 0xFF 709 710 static void 711 wlan_populate_tid_link_id_bitmap(struct wlan_t2lm_info *t2lm, 712 struct mlo_link_info *link_info, 713 struct wlan_diag_mlo_t2lm_status *buf, 714 uint8_t bss_link) 715 { 716 uint8_t link_id; 717 uint8_t dir, i; 718 uint16_t freq; 719 720 link_id = link_info->link_id; 721 freq = link_info->link_chan_info->ch_freq; 722 buf->mlo_cmn_info[bss_link].band = 723 wlan_convert_freq_to_diag_band(freq); 724 buf->mlo_cmn_info[bss_link].vdev_id = link_info->vdev_id; 725 726 for (dir = 0; dir < WLAN_T2LM_MAX_DIRECTION; dir++) { 727 if (t2lm[dir].default_link_mapping) { 728 buf->mlo_cmn_info[bss_link].tid_ul = DEFAULT_TID_MAP; 729 buf->mlo_cmn_info[bss_link].tid_dl = DEFAULT_TID_MAP; 730 continue; 731 } 732 733 for (i = 0; i < T2LM_MAX_NUM_TIDS; i++) { 734 switch (t2lm[dir].direction) { 735 case WLAN_T2LM_DL_DIRECTION: 736 if ( 737 IS_LINK_SET( 738 t2lm[dir].ieee_link_map_tid[i], link_id)) 739 buf->mlo_cmn_info[bss_link].tid_dl |= 740 BIT(i); 741 break; 742 case WLAN_T2LM_UL_DIRECTION: 743 if ( 744 IS_LINK_SET( 745 t2lm[dir].ieee_link_map_tid[i], link_id)) 746 buf->mlo_cmn_info[bss_link].tid_ul |= 747 BIT(i); 748 break; 749 case WLAN_T2LM_BIDI_DIRECTION: 750 if ( 751 IS_LINK_SET( 752 t2lm[dir].ieee_link_map_tid[i], link_id)) { 753 buf->mlo_cmn_info[bss_link].tid_dl |= 754 BIT(i); 755 buf->mlo_cmn_info[bss_link].tid_ul |= 756 BIT(i); 757 } 758 break; 759 default: 760 logging_debug("Invalid direction %d", 761 t2lm[dir].direction); 762 break; 763 } 764 } 765 } 766 } 767 768 void 769 wlan_connectivity_t2lm_status_event(struct wlan_objmgr_vdev *vdev) 770 { 771 uint8_t i = 0, dir, num_links = 0; 772 QDF_STATUS status; 773 struct mlo_link_info *link_info; 774 struct wlan_t2lm_info t2lm[WLAN_T2LM_MAX_DIRECTION] = {0}; 775 776 WLAN_HOST_DIAG_EVENT_DEF(wlan_diag_event, 777 struct wlan_diag_mlo_t2lm_status); 778 779 if (!mlo_is_mld_sta(vdev)) 780 return; 781 782 if (!vdev->mlo_dev_ctx) { 783 logging_err("MLO dev ctx not found"); 784 return; 785 } 786 link_info = mlo_mgr_get_ap_link(vdev); 787 if (!link_info) { 788 logging_err("link_info invalid"); 789 return; 790 } 791 792 if (mlo_mgr_is_link_switch_in_progress(vdev)) 793 return; 794 795 wlan_diag_event.diag_cmn.timestamp_us = qdf_get_time_of_the_day_us(); 796 wlan_diag_event.diag_cmn.ktime_us = qdf_ktime_to_us(qdf_ktime_get()); 797 wlan_diag_event.version = DIAG_MLO_T2LM_STATUS_VERSION_V2; 798 799 for (dir = 0; dir < WLAN_T2LM_MAX_DIRECTION; dir++) 800 t2lm[dir].direction = WLAN_T2LM_INVALID_DIRECTION; 801 802 status = wlan_get_t2lm_mapping_status(vdev, t2lm); 803 if (QDF_IS_STATUS_ERROR(status)) { 804 logging_err("Unable to get t2lm_mapping"); 805 return; 806 } 807 808 for (i = 0; 809 i < WLAN_MAX_ML_BSS_LINKS && i < MAX_NUM_LINKS_PER_EVENT; i++) { 810 if (qdf_is_macaddr_zero(&link_info->ap_link_addr) && 811 link_info->link_id == WLAN_INVALID_LINK_ID) 812 continue; 813 814 wlan_populate_tid_link_id_bitmap(t2lm, link_info, 815 &wlan_diag_event, num_links); 816 link_info++; 817 num_links++; 818 } 819 820 wlan_diag_event.num_links = num_links; 821 822 WLAN_HOST_DIAG_EVENT_REPORT(&wlan_diag_event, 823 EVENT_WLAN_MLO_T2LM_STATUS); 824 } 825 826 #else 827 static QDF_STATUS 828 wlan_populate_link_addr(struct wlan_objmgr_vdev *vdev, 829 struct wlan_diag_sta_info *wlan_diag_event) 830 { 831 return QDF_STATUS_SUCCESS; 832 } 833 #endif 834 835 void 836 wlan_cdp_set_peer_freq(struct wlan_objmgr_psoc *psoc, uint8_t *peer_mac, 837 uint32_t freq, uint8_t vdev_id) 838 { 839 ol_txrx_soc_handle soc_txrx_handle; 840 cdp_config_param_type val = {0}; 841 842 soc_txrx_handle = wlan_psoc_get_dp_handle(psoc); 843 844 val.cdp_peer_param_freq = freq; 845 cdp_txrx_set_peer_param(soc_txrx_handle, vdev_id, peer_mac, 846 CDP_CONFIG_PEER_FREQ, val); 847 } 848 849 void 850 wlan_connectivity_sta_info_event(struct wlan_objmgr_psoc *psoc, uint8_t vdev_id, 851 bool is_roam) 852 { 853 QDF_STATUS status; 854 struct wlan_objmgr_vdev *vdev = NULL; 855 856 WLAN_HOST_DIAG_EVENT_DEF(wlan_diag_event, struct wlan_diag_sta_info); 857 858 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id, 859 WLAN_MLME_OBJMGR_ID); 860 if (!vdev) { 861 logging_err_rl("Invalid vdev:%d", vdev_id); 862 return; 863 } 864 865 if (wlan_vdev_mlme_get_opmode(vdev) != QDF_STA_MODE || 866 (wlan_vdev_mlme_is_mlo_vdev(vdev) && 867 (wlan_vdev_mlme_is_mlo_link_switch_in_progress(vdev) || 868 wlan_vdev_mlme_is_mlo_link_vdev(vdev)))) 869 goto out; 870 871 if (!is_roam && !wlan_cm_is_first_candidate_connect_attempt(vdev)) 872 goto out; 873 874 wlan_diag_event.diag_cmn.timestamp_us = qdf_get_time_of_the_day_us(); 875 wlan_diag_event.diag_cmn.ktime_us = qdf_ktime_to_us(qdf_ktime_get()); 876 wlan_diag_event.diag_cmn.vdev_id = vdev_id; 877 wlan_diag_event.is_mlo = wlan_vdev_mlme_is_mlo_vdev(vdev); 878 879 if (wlan_diag_event.is_mlo) { 880 qdf_mem_copy(wlan_diag_event.diag_cmn.bssid, 881 wlan_vdev_mlme_get_mldaddr(vdev), 882 QDF_MAC_ADDR_SIZE); 883 status = wlan_populate_link_addr(vdev, &wlan_diag_event); 884 if (QDF_IS_STATUS_ERROR(status)) { 885 logging_err_rl("wlan_populate_link_addr failed"); 886 goto out; 887 } 888 } else { 889 qdf_mem_copy(wlan_diag_event.diag_cmn.bssid, 890 wlan_vdev_mlme_get_macaddr(vdev), 891 QDF_MAC_ADDR_SIZE); 892 } 893 894 WLAN_HOST_DIAG_EVENT_REPORT(&wlan_diag_event, EVENT_WLAN_STA_INFO); 895 out: 896 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_OBJMGR_ID); 897 } 898 899 void 900 wlan_populate_vsie(struct wlan_objmgr_vdev *vdev, 901 struct wlan_diag_packet_info *data, 902 bool is_tx) 903 { 904 struct element_info *vsie_info = NULL; 905 906 if (is_tx) 907 vsie_info = mlme_get_self_disconnect_ies(vdev); 908 else 909 vsie_info = mlme_get_peer_disconnect_ies(vdev); 910 911 if (!vsie_info) 912 return; 913 914 data->vsie_len = vsie_info->len; 915 if (data->vsie_len > MAX_VSIE_LEN) 916 data->vsie_len = MAX_VSIE_LEN; 917 918 qdf_mem_copy(data->vsie, vsie_info->ptr, data->vsie_len); 919 } 920 921 void 922 wlan_connectivity_mgmt_event(struct wlan_objmgr_psoc *psoc, 923 struct wlan_frame_hdr *mac_hdr, 924 uint8_t vdev_id, uint16_t status_code, 925 enum qdf_dp_tx_rx_status tx_status, 926 int8_t peer_rssi, 927 uint8_t auth_algo, uint8_t auth_type, 928 uint8_t auth_seq, uint16_t aid, 929 enum wlan_main_tag tag) 930 { 931 enum QDF_OPMODE opmode; 932 bool cache_sae_frame_cap, is_initial_connection; 933 struct wlan_objmgr_vdev *vdev; 934 QDF_STATUS status; 935 936 WLAN_HOST_DIAG_EVENT_DEF(wlan_diag_event, struct wlan_diag_packet_info); 937 938 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id, 939 WLAN_MLME_OBJMGR_ID); 940 if (!vdev) { 941 logging_debug("Unable to find vdev:%d", vdev_id); 942 return; 943 } 944 945 opmode = wlan_vdev_mlme_get_opmode(vdev); 946 if (opmode != QDF_STA_MODE) 947 goto out; 948 949 is_initial_connection = wlan_cm_is_vdev_connecting(vdev); 950 if (wlan_vdev_mlme_is_mlo_vdev(vdev) && 951 (wlan_vdev_mlme_is_mlo_link_switch_in_progress(vdev) || 952 (is_initial_connection && 953 wlan_vdev_mlme_is_mlo_link_vdev(vdev)))) { 954 logging_debug("vdev:%d is_connection:%d | %s skip mgmt event", 955 vdev_id, is_initial_connection, 956 wlan_vdev_mlme_is_mlo_link_vdev(vdev) ? 957 "link_vdev" : wlan_vdev_mlme_is_mlo_link_switch_in_progress(vdev) ? "link switch in prog" : ""); 958 goto out; 959 } 960 961 qdf_mem_zero(&wlan_diag_event, sizeof(struct wlan_diag_packet_info)); 962 963 wlan_diag_event.diag_cmn.timestamp_us = qdf_get_time_of_the_day_us(); 964 wlan_diag_event.diag_cmn.ktime_us = qdf_ktime_to_us(qdf_ktime_get()); 965 wlan_diag_event.diag_cmn.vdev_id = vdev_id; 966 wlan_diag_event.subtype = (uint8_t)tag; 967 968 qdf_mem_copy(wlan_diag_event.diag_cmn.bssid, &mac_hdr->i_addr3[0], 969 QDF_MAC_ADDR_SIZE); 970 971 if (is_initial_connection) { 972 status = wlan_populate_mlo_mgmt_event_param(vdev, 973 &wlan_diag_event, 974 tag); 975 if (QDF_IS_STATUS_ERROR(status)) 976 goto out; 977 } 978 979 wlan_diag_event.version = DIAG_MGMT_VERSION_V2; 980 wlan_diag_event.tx_fail_reason = tx_status; 981 wlan_diag_event.tx_status = wlan_get_diag_tx_status(tx_status); 982 wlan_diag_event.rssi = peer_rssi; 983 wlan_diag_event.sn = 984 (le16toh(*(uint16_t *)mac_hdr->i_seq) >> WLAN_SEQ_SEQ_SHIFT); 985 wlan_diag_event.status = status_code; 986 wlan_diag_event.auth_algo = auth_algo; 987 wlan_diag_event.auth_frame_type = auth_type; 988 wlan_diag_event.auth_seq_num = auth_seq; 989 wlan_diag_event.assoc_id = aid; 990 991 if (tag == WLAN_DEAUTH_RX || tag == WLAN_DISASSOC_RX) 992 wlan_populate_vsie(vdev, &wlan_diag_event, false); 993 994 if (wlan_diag_event.subtype > WLAN_CONN_DIAG_REASSOC_RESP_EVENT && 995 wlan_diag_event.subtype < WLAN_CONN_DIAG_BMISS_EVENT) 996 wlan_diag_event.reason = status_code; 997 998 wlan_diag_event.is_retry_frame = 999 (mac_hdr->i_fc[1] & IEEE80211_FC1_RETRY); 1000 1001 /* 1002 * Cache the SAE auth frames info in vdev mlme private and return in 1003 * case of roam preauth 1004 */ 1005 cache_sae_frame_cap = 1006 wlan_psoc_nif_fw_ext2_cap_get(psoc, 1007 WLAN_ROAM_STATS_FRAME_INFO_PER_CANDIDATE); 1008 if (!is_initial_connection && 1009 (tag == WLAN_AUTH_REQ || tag == WLAN_AUTH_RESP) && 1010 auth_algo == WLAN_SAE_AUTH_ALGO_NUMBER && cache_sae_frame_cap) { 1011 wlan_cache_connectivity_log(psoc, vdev_id, &wlan_diag_event); 1012 goto out; 1013 } 1014 1015 WLAN_HOST_DIAG_EVENT_REPORT(&wlan_diag_event, EVENT_WLAN_MGMT); 1016 1017 if (tag == WLAN_ASSOC_RSP || tag == WLAN_REASSOC_RSP) 1018 wlan_connectivity_mlo_setup_event(vdev); 1019 1020 out: 1021 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_OBJMGR_ID); 1022 } 1023 1024 void 1025 wlan_connectivity_connecting_event(struct wlan_objmgr_vdev *vdev, 1026 struct wlan_cm_connect_req *con_req) 1027 { 1028 QDF_STATUS status; 1029 struct wlan_cm_connect_req req; 1030 1031 WLAN_HOST_DIAG_EVENT_DEF(wlan_diag_event, struct wlan_diag_connect); 1032 1033 if (!wlan_cm_is_first_candidate_connect_attempt(vdev)) 1034 return; 1035 1036 /* for candidate not found case*/ 1037 if (con_req) { 1038 req = *con_req; 1039 qdf_mem_zero(&req.scan_ie, sizeof(struct element_info)); 1040 qdf_mem_zero(&req.assoc_ie, sizeof(struct element_info)); 1041 } else { 1042 status = wlan_cm_get_active_connect_req_param(vdev, &req); 1043 if (QDF_IS_STATUS_ERROR(status)) { 1044 logging_err("vdev: %d failed to get active cmd request", 1045 wlan_vdev_get_id(vdev)); 1046 return; 1047 } 1048 } 1049 1050 wlan_diag_event.version = DIAG_CONN_VERSION; 1051 wlan_diag_event.diag_cmn.timestamp_us = qdf_get_time_of_the_day_us(); 1052 wlan_diag_event.diag_cmn.ktime_us = qdf_ktime_to_us(qdf_ktime_get()); 1053 wlan_diag_event.diag_cmn.vdev_id = wlan_vdev_get_id(vdev); 1054 wlan_diag_event.subtype = WLAN_CONN_DIAG_CONNECTING_EVENT; 1055 1056 wlan_diag_event.ssid_len = req.ssid.length; 1057 1058 if (req.ssid.length > WLAN_SSID_MAX_LEN) 1059 wlan_diag_event.ssid_len = WLAN_SSID_MAX_LEN; 1060 1061 qdf_mem_copy(wlan_diag_event.ssid, req.ssid.ssid, 1062 wlan_diag_event.ssid_len); 1063 1064 if (!qdf_is_macaddr_zero(&req.bssid)) 1065 qdf_mem_copy(wlan_diag_event.diag_cmn.bssid, req.bssid.bytes, 1066 QDF_MAC_ADDR_SIZE); 1067 else if (!qdf_is_macaddr_zero(&req.bssid_hint)) 1068 qdf_mem_copy(wlan_diag_event.bssid_hint, req.bssid_hint.bytes, 1069 QDF_MAC_ADDR_SIZE); 1070 1071 if (req.chan_freq) 1072 wlan_diag_event.freq = req.chan_freq; 1073 else if (req.chan_freq_hint) 1074 wlan_diag_event.freq_hint = req.chan_freq_hint; 1075 1076 wlan_diag_event.pairwise_cipher = req.crypto.user_cipher_pairwise; 1077 wlan_diag_event.grp_cipher = req.crypto.user_grp_cipher; 1078 wlan_diag_event.akm = req.crypto.user_akm_suite; 1079 wlan_diag_event.auth_algo = req.crypto.user_auth_type; 1080 1081 if (req.scan_ie.len) { 1082 qdf_mem_free(req.scan_ie.ptr); 1083 qdf_mem_zero(&req.scan_ie, sizeof(struct element_info)); 1084 } 1085 1086 if (req.assoc_ie.len) { 1087 qdf_mem_free(req.assoc_ie.ptr); 1088 qdf_mem_zero(&req.assoc_ie, sizeof(struct element_info)); 1089 } 1090 1091 wlan_diag_event.bt_coex = 1092 wlan_mlme_get_bt_profile_con(wlan_vdev_get_psoc(vdev)); 1093 1094 WLAN_HOST_DIAG_EVENT_REPORT(&wlan_diag_event, EVENT_WLAN_CONN); 1095 } 1096 1097 #ifdef WLAN_FEATURE_11BE_MLO 1098 1099 #define BAND_TO_BITMAP(band) (band - 1) 1100 1101 static uint8_t 1102 wlan_convert_link_id_to_diag_band(struct qdf_mac_addr *peer_mld, 1103 uint16_t link_bitmap) 1104 { 1105 uint8_t i, band_bitmap = 0, band; 1106 struct wlan_mlo_dev_context *mldev = NULL; 1107 struct wlan_mlo_peer_context *mlpeer = NULL; 1108 struct mlo_link_info *link_info = NULL; 1109 uint32_t freq; 1110 1111 mlpeer = wlan_mlo_get_mlpeer_by_peer_mladdr(peer_mld, &mldev); 1112 if (!mlpeer) { 1113 logging_err("ml peer not found"); 1114 return 0; 1115 } 1116 1117 for (i = 0; i < MAX_MLO_LINK_ID; i++) { 1118 if (IS_LINK_SET(link_bitmap, i)) { 1119 link_info = mlo_mgr_get_ap_link_by_link_id(mldev, i); 1120 if (!link_info) { 1121 logging_err("link: %d info does not exist", i); 1122 return 0; 1123 } 1124 1125 freq = link_info->link_chan_info->ch_freq; 1126 band = wlan_convert_freq_to_diag_band(freq); 1127 if (band == WLAN_INVALID_BAND) 1128 continue; 1129 1130 band_bitmap |= BIT(BAND_TO_BITMAP(band)); 1131 } 1132 } 1133 1134 return band_bitmap; 1135 } 1136 1137 static uint8_t 1138 wlan_get_supported_link_band_bitmap(struct mlo_link_switch_context *link_ctx) 1139 { 1140 uint8_t band_bitmap = 0, i = 0; 1141 struct mlo_link_info link_info; 1142 struct wlan_channel *chan_info; 1143 enum wlan_diag_wifi_band band; 1144 1145 for (i = 0; i < WLAN_MAX_ML_BSS_LINKS; i++) { 1146 link_info = link_ctx->links_info[i]; 1147 1148 chan_info = link_info.link_chan_info; 1149 if (!chan_info) 1150 continue; 1151 1152 band = wlan_convert_freq_to_diag_band(chan_info->ch_freq); 1153 if (band == WLAN_INVALID_BAND) 1154 continue; 1155 1156 band_bitmap |= BIT(band - 1); 1157 } 1158 1159 return band_bitmap; 1160 } 1161 1162 void wlan_connectivity_mld_link_status_event(struct wlan_objmgr_psoc *psoc, 1163 struct mlo_link_switch_params *src) 1164 { 1165 struct wlan_mlo_peer_context *ml_peer = NULL; 1166 struct wlan_mlo_dev_context *mld_ctx = NULL; 1167 1168 WLAN_HOST_DIAG_EVENT_DEF(wlan_diag_event, 1169 struct wlan_diag_mlo_link_status); 1170 1171 qdf_mem_zero(&wlan_diag_event, 1172 sizeof(struct wlan_diag_mlo_link_status)); 1173 1174 ml_peer = wlan_mlo_get_mlpeer_by_peer_mladdr(&src->mld_addr, &mld_ctx); 1175 1176 if (!mld_ctx) { 1177 logging_err("mlo dev ctx for mld_mac: " 1178 QDF_MAC_ADDR_FMT 1179 " not found", 1180 QDF_MAC_ADDR_REF(src->mld_addr.bytes)); 1181 return; 1182 } 1183 1184 wlan_diag_event.diag_cmn.timestamp_us = qdf_get_time_of_the_day_us(); 1185 wlan_diag_event.diag_cmn.ktime_us = qdf_ktime_to_us(qdf_ktime_get()); 1186 wlan_diag_event.version = DIAG_MLO_LINK_STATUS_VERSION_2; 1187 1188 wlan_diag_event.active_link = 1189 wlan_convert_link_id_to_diag_band(&src->mld_addr, 1190 src->active_link_bitmap); 1191 if (!wlan_diag_event.active_link) 1192 return; 1193 wlan_diag_event.prev_active_link = 1194 wlan_convert_link_id_to_diag_band(&src->mld_addr, 1195 src->prev_link_bitmap); 1196 if (!wlan_diag_event.prev_active_link) 1197 return; 1198 1199 if (!mld_ctx->link_ctx) { 1200 logging_err("link ctx for mld_mac: " 1201 QDF_MAC_ADDR_FMT 1202 " not found", 1203 QDF_MAC_ADDR_REF(src->mld_addr.bytes)); 1204 return; 1205 } 1206 1207 wlan_diag_event.associated_links = 1208 wlan_get_supported_link_band_bitmap(mld_ctx->link_ctx); 1209 1210 if (!wlan_diag_event.associated_links) 1211 return; 1212 1213 wlan_diag_event.reason = src->reason_code; 1214 /* 1215 * FW timestamp received from FW in milliseconds and to be sent to 1216 * userspace in microseconds 1217 */ 1218 wlan_diag_event.diag_cmn.fw_timestamp = src->fw_timestamp * 1000; 1219 1220 WLAN_HOST_DIAG_EVENT_REPORT(&wlan_diag_event, 1221 EVENT_WLAN_MLO_LINK_STATUS); 1222 } 1223 #endif 1224 #endif 1225