1 /* 2 * Copyright (c) 2021, The Linux Foundation. All rights reserved. 3 * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for 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 #include "wlan_mlo_mgr_main.h" 19 #include "qdf_types.h" 20 #include "wlan_cmn.h" 21 #include "wlan_mlo_mgr_peer.h" 22 #include <wlan_mlo_mgr_ap.h> 23 #include <wlan_mlo_mgr_setup.h> 24 #include <wlan_utility.h> 25 #include <wlan_reg_services_api.h> 26 27 /** 28 * struct mlpeer_data: PSOC peers MLO data 29 * @total_rssi: sum of RSSI of all ML peers 30 * @num_ml_peers: Number of ML peer's with this PSOC as TQM 31 * @max_ml_peers: Max ML peers can have this PSOC as TQM 32 * (it is to distribute peers across all PSOCs) 33 * @num_non_ml_peers: Non MLO peers of this PSOC 34 */ 35 struct mlpeer_data { 36 int32_t total_rssi; 37 uint16_t num_ml_peers; 38 uint16_t max_ml_peers; 39 uint16_t num_non_ml_peers; 40 }; 41 42 /** 43 * struct mlo_all_link_rssi: structure to collect TQM params for all PSOCs 44 * @psoc_tqm_parms: It collects peer data for all PSOCs 45 * @num_psocs: Number of PSOCs in the system 46 * @current_psoc_id: current psoc id, it is for iterator 47 */ 48 struct mlo_all_link_rssi { 49 struct mlpeer_data psoc_tqm_parms[WLAN_OBJMGR_MAX_DEVICES]; 50 uint8_t num_psocs; 51 uint8_t current_psoc_id; 52 }; 53 54 /* Invalid TQM/PSOC ID */ 55 #define ML_INVALID_PRIMARY_TQM 0xff 56 /* Congestion value */ 57 #define ML_PRIMARY_TQM_CONGESTION 30 58 59 static void wlan_mlo_peer_get_rssi(struct wlan_objmgr_psoc *psoc, 60 void *obj, void *args) 61 { 62 struct wlan_mlo_peer_context *mlo_peer_ctx; 63 struct wlan_objmgr_peer *peer = (struct wlan_objmgr_peer *)obj; 64 struct mlo_all_link_rssi *rssi_data = (struct mlo_all_link_rssi *)args; 65 struct mlpeer_data *tqm_params = NULL; 66 uint8_t index; 67 68 mlo_peer_ctx = peer->mlo_peer_ctx; 69 index = rssi_data->current_psoc_id; 70 tqm_params = &rssi_data->psoc_tqm_parms[index]; 71 72 if (!wlan_peer_is_mlo(peer) && !mlo_peer_ctx) { 73 if (wlan_peer_get_peer_type(peer) == WLAN_PEER_STA) 74 tqm_params->num_non_ml_peers += 1; 75 return; 76 } 77 78 if (!mlo_peer_ctx) 79 return; 80 81 /* If this psoc is not primary UMAC, don't account RSSI */ 82 if (mlo_peer_ctx->primary_umac_psoc_id != rssi_data->current_psoc_id) 83 return; 84 85 tqm_params->total_rssi += mlo_peer_ctx->avg_link_rssi; 86 tqm_params->num_ml_peers += 1; 87 } 88 89 static void wlan_get_rssi_data_each_psoc(struct wlan_objmgr_psoc *psoc, 90 void *arg, uint8_t index) 91 { 92 struct mlo_all_link_rssi *rssi_data = (struct mlo_all_link_rssi *)arg; 93 struct mlpeer_data *tqm_params = NULL; 94 95 tqm_params = &rssi_data->psoc_tqm_parms[index]; 96 97 tqm_params->total_rssi = 0; 98 tqm_params->num_ml_peers = 0; 99 tqm_params->num_non_ml_peers = 0; 100 tqm_params->max_ml_peers = MAX_MLO_PEER; 101 102 rssi_data->current_psoc_id = index; 103 rssi_data->num_psocs++; 104 105 wlan_objmgr_iterate_obj_list(psoc, WLAN_PEER_OP, 106 wlan_mlo_peer_get_rssi, rssi_data, 0, 107 WLAN_MLO_MGR_ID); 108 } 109 110 static QDF_STATUS mld_get_link_rssi(struct mlo_all_link_rssi *rssi_data) 111 { 112 rssi_data->num_psocs = 0; 113 114 wlan_objmgr_iterate_psoc_list(wlan_get_rssi_data_each_psoc, 115 rssi_data, WLAN_MLO_MGR_ID); 116 117 return QDF_STATUS_SUCCESS; 118 } 119 120 static void 121 mld_get_best_primary_umac_w_rssi(struct wlan_mlo_peer_context *ml_peer, 122 struct wlan_objmgr_vdev *link_vdevs[]) 123 { 124 struct mlo_all_link_rssi rssi_data; 125 uint8_t i; 126 int32_t avg_rssi[WLAN_OBJMGR_MAX_DEVICES] = {0}; 127 int32_t diff_rssi[WLAN_OBJMGR_MAX_DEVICES] = {0}; 128 int32_t diff_low; 129 bool mld_sta_links[WLAN_OBJMGR_MAX_DEVICES] = {0}; 130 bool mld_no_sta[WLAN_OBJMGR_MAX_DEVICES] = {0}; 131 struct wlan_objmgr_peer *assoc_peer = NULL; 132 uint8_t prim_link, id; 133 uint8_t num_psocs; 134 struct mlpeer_data *tqm_params = NULL; 135 struct wlan_channel *channel; 136 enum phy_ch_width chwidth; 137 uint8_t cong = ML_PRIMARY_TQM_CONGESTION; 138 uint16_t mld_ml_sta_count[WLAN_OBJMGR_MAX_DEVICES] = {0}; 139 enum phy_ch_width mld_ch_width[WLAN_OBJMGR_MAX_DEVICES]; 140 uint8_t psoc_w_nosta; 141 uint16_t ml_sta_count = 0; 142 uint32_t total_cap, cap; 143 uint16_t bw; 144 bool group_full[WLAN_OBJMGR_MAX_DEVICES] = {0}; 145 uint16_t group_size[WLAN_OBJMGR_MAX_DEVICES] = {0}; 146 uint16_t grp_size = 0; 147 uint16_t group_full_count = 0; 148 149 mld_get_link_rssi(&rssi_data); 150 151 for (i = 0; i < rssi_data.num_psocs; i++) { 152 tqm_params = &rssi_data.psoc_tqm_parms[i]; 153 154 if (tqm_params->num_ml_peers) 155 avg_rssi[i] = (tqm_params->total_rssi / 156 tqm_params->num_ml_peers); 157 } 158 159 /** 160 * If MLD STA associated to a set of links, choose primary UMAC 161 * from those links only 162 */ 163 num_psocs = 0; 164 psoc_w_nosta = 0; 165 for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) 166 mld_ch_width[i] = CH_WIDTH_INVALID; 167 168 for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) { 169 if (!link_vdevs[i]) 170 continue; 171 172 id = wlan_vdev_get_psoc_id(link_vdevs[i]); 173 if (id >= WLAN_OBJMGR_MAX_DEVICES) 174 continue; 175 176 if (wlan_vdev_skip_pumac(link_vdevs[i])) { 177 mlo_err("Skip Radio for Primary MLO umac"); 178 mld_sta_links[id] = false; 179 continue; 180 } 181 182 tqm_params = &rssi_data.psoc_tqm_parms[id]; 183 mld_sta_links[id] = true; 184 185 channel = wlan_vdev_mlme_get_bss_chan(link_vdevs[i]); 186 mld_ch_width[id] = channel->ch_width; 187 188 if ((tqm_params->num_ml_peers + 189 tqm_params->num_non_ml_peers) == 0) { 190 /* If this PSOC has no stations */ 191 mld_no_sta[id] = true; 192 psoc_w_nosta++; 193 } 194 195 mld_ml_sta_count[id] = tqm_params->num_ml_peers; 196 /* Update total MLO STA count */ 197 ml_sta_count += tqm_params->num_ml_peers; 198 199 num_psocs++; 200 201 /* If no stations are associated, derive diff rssi 202 * based on psoc id {0-20, 20-40, 40 } so that 203 * stations are distributed across TQMs 204 */ 205 if (!avg_rssi[id]) { 206 diff_rssi[id] = (id * 20); 207 continue; 208 } 209 diff_rssi[id] = (ml_peer->avg_link_rssi >= avg_rssi[id]) ? 210 (ml_peer->avg_link_rssi - avg_rssi[id]) : 211 (avg_rssi[id] - ml_peer->avg_link_rssi); 212 213 } 214 215 prim_link = ML_INVALID_PRIMARY_TQM; 216 217 /* If one of the PSOCs doesn't have any station select that PSOC as 218 * primary TQM. If more than one PSOC have no stations as Primary TQM 219 * the vdev with less bw needs to be selected as Primary TQM 220 */ 221 if (psoc_w_nosta == 1) { 222 for (i = 0; i < WLAN_OBJMGR_MAX_DEVICES; i++) { 223 if (mld_no_sta[i]) { 224 prim_link = i; 225 break; 226 } 227 } 228 } else if (psoc_w_nosta > 1) { 229 chwidth = CH_WIDTH_INVALID; 230 for (i = 0; i < WLAN_OBJMGR_MAX_DEVICES; i++) { 231 if (!mld_no_sta[i]) 232 continue; 233 234 if (chwidth == CH_WIDTH_INVALID) { 235 prim_link = i; 236 chwidth = mld_ch_width[i]; 237 continue; 238 } 239 240 /* If bw is less than or equal to 160 MHZ 241 * and chwidth is less than other link 242 * Mark this link as primary link 243 */ 244 if ((mld_ch_width[i] <= CH_WIDTH_160MHZ) && 245 (chwidth > mld_ch_width[i])) { 246 prim_link = i; 247 chwidth = mld_ch_width[i]; 248 } 249 } 250 } else { 251 total_cap = 0; 252 for (i = 0; i < WLAN_OBJMGR_MAX_DEVICES; i++) { 253 bw = wlan_reg_get_bw_value(mld_ch_width[i]); 254 total_cap += bw * (100 - cong); 255 } 256 257 group_full_count = 0; 258 for (i = 0; i < WLAN_OBJMGR_MAX_DEVICES; i++) { 259 if (!mld_sta_links[i]) 260 continue; 261 262 bw = wlan_reg_get_bw_value(mld_ch_width[i]); 263 cap = bw * (100 - cong); 264 grp_size = (ml_sta_count) * ((cap * 100) / total_cap); 265 group_size[i] = grp_size / 100; 266 if (group_size[i] <= mld_ml_sta_count[i]) { 267 group_full[i] = true; 268 group_full_count++; 269 } 270 } 271 272 if ((num_psocs - group_full_count) == 1) { 273 for (i = 0; i < WLAN_OBJMGR_MAX_DEVICES; i++) { 274 if (!mld_sta_links[i]) 275 continue; 276 277 if (group_full[i]) 278 continue; 279 280 prim_link = i; 281 break; 282 } 283 } else { 284 diff_low = 0; 285 /* find min diff, based on it, allocate primary umac */ 286 for (i = 0; i < WLAN_OBJMGR_MAX_DEVICES; i++) { 287 if (!mld_sta_links[i]) 288 continue; 289 290 /* First iteration */ 291 if (diff_low == 0) { 292 diff_low = diff_rssi[i]; 293 prim_link = i; 294 } else if (diff_low > diff_rssi[i]) { 295 diff_low = diff_rssi[i]; 296 prim_link = i; 297 } 298 } 299 } 300 } 301 302 if (prim_link != ML_INVALID_PRIMARY_TQM) { 303 ml_peer->primary_umac_psoc_id = prim_link; 304 } else { 305 assoc_peer = wlan_mlo_peer_get_assoc_peer(ml_peer); 306 if (!assoc_peer) { 307 mlo_err(QDF_MAC_ADDR_FMT ":Assoc peer is NULL", 308 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes)); 309 QDF_BUG(0); 310 return; 311 } 312 ml_peer->primary_umac_psoc_id = 313 wlan_peer_get_psoc_id(assoc_peer); 314 } 315 } 316 317 void mlo_peer_assign_primary_umac( 318 struct wlan_mlo_peer_context *ml_peer, 319 struct wlan_mlo_link_peer_entry *peer_entry) 320 { 321 struct wlan_mlo_link_peer_entry *peer_ent_iter; 322 uint8_t i; 323 uint8_t primary_umac_set = 0; 324 325 /* If MLD is within single SOC, then assoc link becomes 326 * primary umac 327 */ 328 if (ml_peer->primary_umac_psoc_id == ML_PRIMARY_UMAC_ID_INVAL) { 329 if (wlan_peer_mlme_is_assoc_peer(peer_entry->link_peer)) { 330 peer_entry->is_primary = true; 331 ml_peer->primary_umac_psoc_id = 332 wlan_peer_get_psoc_id(peer_entry->link_peer); 333 } else { 334 peer_entry->is_primary = false; 335 } 336 } else { 337 /* If this peer PSOC is not derived as Primary PSOC, 338 * mark is_primary as false 339 */ 340 if (wlan_peer_get_psoc_id(peer_entry->link_peer) != 341 ml_peer->primary_umac_psoc_id) { 342 peer_entry->is_primary = false; 343 return; 344 } 345 346 /* For single SOC, check whether is_primary is set for 347 * other partner peer, then mark is_primary false for this peer 348 */ 349 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) { 350 peer_ent_iter = &ml_peer->peer_list[i]; 351 352 if (!peer_ent_iter->link_peer) 353 continue; 354 355 /* Check for other link peers */ 356 if (peer_ent_iter == peer_entry) 357 continue; 358 359 if (wlan_peer_get_psoc_id(peer_ent_iter->link_peer) != 360 ml_peer->primary_umac_psoc_id) 361 continue; 362 363 if (peer_ent_iter->is_primary) 364 primary_umac_set = 1; 365 } 366 367 if (primary_umac_set) 368 peer_entry->is_primary = false; 369 else 370 peer_entry->is_primary = true; 371 } 372 } 373 374 static int8_t wlan_vdev_derive_link_rssi(struct wlan_objmgr_vdev *vdev, 375 struct wlan_objmgr_vdev *assoc_vdev, 376 int8_t rssi) 377 { 378 struct wlan_channel *channel, *assoc_channel; 379 uint16_t ch_freq, assoc_freq; 380 uint8_t tx_pow, assoc_tx_pow; 381 int8_t diff_txpow; 382 struct wlan_objmgr_pdev *pdev, *assoc_pdev; 383 uint8_t log10_freq; 384 uint8_t derived_rssi; 385 int16_t ten_derived_rssi; 386 int8_t ten_diff_pl = 0; 387 388 pdev = wlan_vdev_get_pdev(vdev); 389 assoc_pdev = wlan_vdev_get_pdev(assoc_vdev); 390 391 channel = wlan_vdev_get_active_channel(vdev); 392 if (channel) 393 ch_freq = channel->ch_freq; 394 else 395 ch_freq = 1; 396 397 assoc_channel = wlan_vdev_get_active_channel(assoc_vdev); 398 if (assoc_channel) 399 assoc_freq = assoc_channel->ch_freq; 400 else 401 assoc_freq = 1; 402 403 /* 404 * diff of path loss (of two links) = log10(freq1) - log10(freq2) 405 * (since distance is constant) 406 * since log10 is not available, we cameup with approximate ranges 407 */ 408 log10_freq = (ch_freq * 10) / assoc_freq; 409 if ((log10_freq >= 20) && (log10_freq < 30)) 410 ten_diff_pl = 4; /* 0.4 *10 */ 411 else if ((log10_freq >= 11) && (log10_freq < 20)) 412 ten_diff_pl = 1; /* 0.1 *10 */ 413 else if ((log10_freq >= 8) && (log10_freq < 11)) 414 ten_diff_pl = 0; /* 0 *10 */ 415 else if ((log10_freq >= 4) && (log10_freq < 8)) 416 ten_diff_pl = -1; /* -0.1 * 10 */ 417 else if ((log10_freq >= 1) && (log10_freq < 4)) 418 ten_diff_pl = -4; /* -0.4 * 10 */ 419 420 assoc_tx_pow = wlan_reg_get_channel_reg_power_for_freq(assoc_pdev, 421 assoc_freq); 422 tx_pow = wlan_reg_get_channel_reg_power_for_freq(pdev, ch_freq); 423 424 diff_txpow = tx_pow - assoc_tx_pow; 425 426 ten_derived_rssi = (diff_txpow * 10) - ten_diff_pl + (rssi * 10); 427 derived_rssi = ten_derived_rssi / 10; 428 429 return derived_rssi; 430 } 431 432 static void mlo_peer_calculate_avg_rssi( 433 struct wlan_mlo_dev_context *ml_dev, 434 struct wlan_mlo_peer_context *ml_peer, 435 int8_t rssi, 436 struct wlan_objmgr_vdev *assoc_vdev) 437 { 438 int32_t total_rssi = 0; 439 uint8_t num_psocs = 0; 440 uint8_t i; 441 struct wlan_objmgr_vdev *vdev; 442 443 for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) { 444 vdev = ml_dev->wlan_vdev_list[i]; 445 if (!vdev) 446 continue; 447 448 num_psocs++; 449 if (vdev == assoc_vdev) 450 total_rssi += rssi; 451 else 452 total_rssi += wlan_vdev_derive_link_rssi(vdev, 453 assoc_vdev, 454 rssi); 455 } 456 457 if (!num_psocs) 458 return; 459 460 ml_peer->avg_link_rssi = total_rssi / num_psocs; 461 } 462 463 #ifdef WLAN_MLO_MULTI_CHIP 464 int8_t mlo_get_central_umac_id( 465 uint8_t *psoc_ids) 466 { 467 uint8_t prim_psoc_id = -1; 468 uint8_t adjacent = 0; 469 470 /* Some 3 link RDPs have restriction on the primary umac. 471 * Only the link that is adjacent to both the links can be 472 * a primary umac. 473 * Note: it means umac migration is also restricted. 474 */ 475 mlo_chip_adjacent(psoc_ids[0], psoc_ids[1], &adjacent); 476 if (!adjacent) { 477 prim_psoc_id = psoc_ids[2]; 478 } else { 479 mlo_chip_adjacent(psoc_ids[0], psoc_ids[2], &adjacent); 480 if (!adjacent) { 481 prim_psoc_id = psoc_ids[1]; 482 } else { 483 /* If all links are adjacent to each other, 484 * no need to restrict the primary umac. 485 * return failure the caller will handle. 486 */ 487 mlo_chip_adjacent(psoc_ids[1], psoc_ids[2], 488 &adjacent); 489 if (!adjacent) 490 prim_psoc_id = psoc_ids[0]; 491 else 492 return prim_psoc_id; 493 } 494 } 495 496 return prim_psoc_id; 497 } 498 499 static QDF_STATUS mlo_set_3_link_primary_umac( 500 struct wlan_mlo_peer_context *ml_peer, 501 struct wlan_objmgr_vdev *link_vdevs[]) 502 { 503 uint8_t psoc_ids[WLAN_UMAC_MLO_MAX_VDEVS]; 504 int8_t central_umac_id; 505 506 if (ml_peer->max_links != 3) 507 return QDF_STATUS_E_FAILURE; 508 509 /* Some 3 link RDPs have restriction on the primary umac. 510 * Only the link that is adjacent to both the links can be 511 * a primary umac. 512 * Note: it means umac migration is also restricted. 513 */ 514 psoc_ids[0] = wlan_vdev_get_psoc_id(link_vdevs[0]); 515 psoc_ids[1] = wlan_vdev_get_psoc_id(link_vdevs[1]); 516 psoc_ids[2] = wlan_vdev_get_psoc_id(link_vdevs[2]); 517 518 central_umac_id = mlo_get_central_umac_id(psoc_ids); 519 if (central_umac_id != -1) 520 ml_peer->primary_umac_psoc_id = central_umac_id; 521 else 522 return QDF_STATUS_E_FAILURE; 523 524 mlo_peer_assign_primary_umac(ml_peer, 525 &ml_peer->peer_list[0]); 526 527 return QDF_STATUS_SUCCESS; 528 } 529 #else 530 static QDF_STATUS mlo_set_3_link_primary_umac( 531 struct wlan_mlo_peer_context *ml_peer, 532 struct wlan_objmgr_vdev *link_vdevs[]) 533 { 534 return QDF_STATUS_E_FAILURE; 535 } 536 #endif 537 538 #if defined(WLAN_FEATURE_11BE_MLO) && defined(WLAN_MLO_MULTI_CHIP) 539 QDF_STATUS mlo_peer_overwrite_primary_umac(uint8_t psoc_id, 540 struct wlan_mlo_peer_context *ml_peer) 541 { 542 if (psoc_id >= WLAN_OBJMGR_MAX_DEVICES) 543 return QDF_STATUS_E_FAILURE; 544 if (!ml_peer) 545 return QDF_STATUS_E_FAILURE; 546 547 ml_peer->primary_umac_psoc_id = psoc_id; 548 mlo_peer_assign_primary_umac(ml_peer, &ml_peer->peer_list[0]); 549 550 return QDF_STATUS_SUCCESS; 551 } 552 #endif 553 554 QDF_STATUS mlo_peer_allocate_primary_umac( 555 struct wlan_mlo_dev_context *ml_dev, 556 struct wlan_mlo_peer_context *ml_peer, 557 struct wlan_objmgr_vdev *link_vdevs[]) 558 { 559 struct wlan_mlo_link_peer_entry *peer_entry; 560 struct wlan_objmgr_peer *assoc_peer = NULL; 561 int32_t rssi; 562 struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx(); 563 uint8_t first_link_id = 0; 564 bool primary_umac_set = false; 565 uint8_t i, psoc_id; 566 567 peer_entry = &ml_peer->peer_list[0]; 568 assoc_peer = peer_entry->link_peer; 569 if (!assoc_peer) 570 return QDF_STATUS_E_FAILURE; 571 572 /* For Station mode, assign assoc peer as primary umac */ 573 if (wlan_peer_get_peer_type(assoc_peer) == WLAN_PEER_AP) { 574 mlo_peer_assign_primary_umac(ml_peer, peer_entry); 575 mlo_info("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " primary umac soc %d ", 576 ml_dev->mld_id, 577 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes), 578 ml_peer->primary_umac_psoc_id); 579 580 return QDF_STATUS_SUCCESS; 581 } 582 583 /* Select assoc peer's PSOC as primary UMAC in Multi-chip solution, 584 * 1) for single link MLO connection 585 * 2) if MLD is single chip MLO 586 */ 587 if ((ml_peer->max_links == 1) || 588 (mlo_vdevs_check_single_soc(link_vdevs, ml_peer->max_links))) { 589 mlo_peer_assign_primary_umac(ml_peer, peer_entry); 590 mlo_info("MLD ID %d Assoc peer " QDF_MAC_ADDR_FMT " primary umac soc %d ", 591 ml_dev->mld_id, 592 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes), 593 ml_peer->primary_umac_psoc_id); 594 595 return QDF_STATUS_SUCCESS; 596 } 597 598 if (mlo_set_3_link_primary_umac(ml_peer, link_vdevs) == 599 QDF_STATUS_SUCCESS) { 600 /* If success then the primary umac is restricted and assigned. 601 * if not, there is no restriction, so just fallthrough 602 */ 603 mlo_info("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT 604 " center primary umac soc %d ", 605 ml_dev->mld_id, 606 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes), 607 ml_peer->primary_umac_psoc_id); 608 609 return QDF_STATUS_SUCCESS; 610 } 611 612 if (mlo_ctx->mlo_is_force_primary_umac) { 613 for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) { 614 if (!link_vdevs[i]) 615 continue; 616 617 psoc_id = wlan_vdev_get_psoc_id(link_vdevs[i]); 618 if (!first_link_id) 619 first_link_id = psoc_id; 620 621 if (psoc_id == mlo_ctx->mlo_forced_primary_umac_id) { 622 ml_peer->primary_umac_psoc_id = psoc_id; 623 primary_umac_set = true; 624 break; 625 } 626 } 627 628 if (!primary_umac_set) 629 ml_peer->primary_umac_psoc_id = first_link_id; 630 631 mlo_peer_assign_primary_umac(ml_peer, peer_entry); 632 mlo_info("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " primary umac soc %d ", 633 ml_dev->mld_id, 634 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes), 635 ml_peer->primary_umac_psoc_id); 636 637 return QDF_STATUS_SUCCESS; 638 } 639 640 rssi = wlan_peer_get_rssi(assoc_peer); 641 mlo_peer_calculate_avg_rssi(ml_dev, ml_peer, rssi, 642 wlan_peer_get_vdev(assoc_peer)); 643 644 mld_get_best_primary_umac_w_rssi(ml_peer, link_vdevs); 645 646 mlo_peer_assign_primary_umac(ml_peer, peer_entry); 647 648 mlo_info("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " avg RSSI %d primary umac soc %d ", 649 ml_dev->mld_id, 650 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes), 651 ml_peer->avg_link_rssi, ml_peer->primary_umac_psoc_id); 652 653 return QDF_STATUS_SUCCESS; 654 } 655 656 QDF_STATUS mlo_peer_free_primary_umac( 657 struct wlan_mlo_dev_context *ml_dev, 658 struct wlan_mlo_peer_context *ml_peer) 659 { 660 return QDF_STATUS_SUCCESS; 661 } 662 663 #ifdef QCA_SUPPORT_PRIMARY_LINK_MIGRATE 664 void wlan_objmgr_mlo_update_primary_info(struct wlan_objmgr_peer *peer) 665 { 666 struct wlan_mlo_peer_context *ml_peer = NULL; 667 struct wlan_mlo_link_peer_entry *peer_ent_iter; 668 uint8_t i; 669 670 ml_peer = peer->mlo_peer_ctx; 671 ml_peer->primary_umac_psoc_id = wlan_peer_get_psoc_id(peer); 672 673 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) { 674 peer_ent_iter = &ml_peer->peer_list[i]; 675 676 if (!peer_ent_iter->link_peer) 677 continue; 678 679 if (peer_ent_iter->is_primary) 680 peer_ent_iter->is_primary = false; 681 682 if (peer_ent_iter->link_peer == peer) 683 peer_ent_iter->is_primary = true; 684 } 685 } 686 687 qdf_export_symbol(wlan_objmgr_mlo_update_primary_info); 688 #endif 689