1 /* 2 * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. 3 * 4 * Permission to use, copy, modify, and/or distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the above 6 * copyright notice and this permission notice appear in all copies. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 */ 16 #include <wlan_utility.h> 17 #include <dp_internal.h> 18 #include <dp_htt.h> 19 #include <hal_be_api.h> 20 #include "dp_mlo.h" 21 #include <dp_be.h> 22 #include <dp_htt.h> 23 #include <dp_internal.h> 24 #include <wlan_cfg.h> 25 #include <wlan_mlo_mgr_cmn.h> 26 /* 27 * dp_mlo_ctxt_attach_wifi3 () – Attach DP MLO context 28 * 29 * Return: DP MLO context handle on success, NULL on failure 30 */ 31 struct cdp_mlo_ctxt * 32 dp_mlo_ctxt_attach_wifi3(struct cdp_ctrl_mlo_mgr *ctrl_ctxt) 33 { 34 struct dp_mlo_ctxt *mlo_ctxt = 35 qdf_mem_malloc(sizeof(struct dp_mlo_ctxt)); 36 37 if (!mlo_ctxt) { 38 dp_err("Failed to allocate DP MLO Context"); 39 return NULL; 40 } 41 42 mlo_ctxt->ctrl_ctxt = ctrl_ctxt; 43 44 if (dp_mlo_peer_find_hash_attach_be 45 (mlo_ctxt, DP_MAX_MLO_PEER) != QDF_STATUS_SUCCESS) { 46 dp_err("Failed to allocate peer hash"); 47 qdf_mem_free(mlo_ctxt); 48 return NULL; 49 } 50 51 qdf_get_random_bytes(mlo_ctxt->toeplitz_hash_ipv4, 52 (sizeof(mlo_ctxt->toeplitz_hash_ipv4[0]) * 53 LRO_IPV4_SEED_ARR_SZ)); 54 qdf_get_random_bytes(mlo_ctxt->toeplitz_hash_ipv6, 55 (sizeof(mlo_ctxt->toeplitz_hash_ipv6[0]) * 56 LRO_IPV6_SEED_ARR_SZ)); 57 58 qdf_spinlock_create(&mlo_ctxt->ml_soc_list_lock); 59 return dp_mlo_ctx_to_cdp(mlo_ctxt); 60 } 61 62 qdf_export_symbol(dp_mlo_ctxt_attach_wifi3); 63 64 /* 65 * dp_mlo_ctxt_detach_wifi3 () – Detach DP MLO context 66 * 67 * @ml_ctxt: pointer to DP MLO context 68 * 69 * Return: void 70 */ 71 void dp_mlo_ctxt_detach_wifi3(struct cdp_mlo_ctxt *cdp_ml_ctxt) 72 { 73 struct dp_mlo_ctxt *mlo_ctxt = cdp_mlo_ctx_to_dp(cdp_ml_ctxt); 74 75 if (!cdp_ml_ctxt) 76 return; 77 78 qdf_spinlock_destroy(&mlo_ctxt->ml_soc_list_lock); 79 dp_mlo_peer_find_hash_detach_be(mlo_ctxt); 80 qdf_mem_free(mlo_ctxt); 81 } 82 83 qdf_export_symbol(dp_mlo_ctxt_detach_wifi3); 84 85 /* 86 * dp_mlo_set_soc_by_chip_id() – Add DP soc to ML context soc list 87 * 88 * @ml_ctxt: DP ML context handle 89 * @soc: DP soc handle 90 * @chip_id: MLO chip id 91 * 92 * Return: void 93 */ 94 void dp_mlo_set_soc_by_chip_id(struct dp_mlo_ctxt *ml_ctxt, 95 struct dp_soc *soc, 96 uint8_t chip_id) 97 { 98 qdf_spin_lock_bh(&ml_ctxt->ml_soc_list_lock); 99 ml_ctxt->ml_soc_list[chip_id] = soc; 100 qdf_spin_unlock_bh(&ml_ctxt->ml_soc_list_lock); 101 } 102 103 /* 104 * dp_mlo_get_soc_ref_by_chip_id() – Get DP soc from DP ML context. 105 * This API will increment a reference count for DP soc. Caller has 106 * to take care for decrementing refcount. 107 * 108 * @ml_ctxt: DP ML context handle 109 * @chip_id: MLO chip id 110 * 111 * Return: dp_soc 112 */ 113 struct dp_soc* 114 dp_mlo_get_soc_ref_by_chip_id(struct dp_mlo_ctxt *ml_ctxt, 115 uint8_t chip_id) 116 { 117 struct dp_soc *soc = NULL; 118 119 if (!ml_ctxt) { 120 dp_warn("MLO context not created, MLO not enabled"); 121 return NULL; 122 } 123 124 qdf_spin_lock_bh(&ml_ctxt->ml_soc_list_lock); 125 soc = ml_ctxt->ml_soc_list[chip_id]; 126 127 if (!soc) { 128 qdf_spin_unlock_bh(&ml_ctxt->ml_soc_list_lock); 129 return NULL; 130 } 131 132 qdf_atomic_inc(&soc->ref_count); 133 qdf_spin_unlock_bh(&ml_ctxt->ml_soc_list_lock); 134 135 return soc; 136 } 137 138 static QDF_STATUS dp_partner_soc_rx_hw_cc_init(struct dp_mlo_ctxt *mlo_ctxt, 139 struct dp_soc_be *be_soc) 140 { 141 uint8_t i; 142 struct dp_soc *partner_soc; 143 struct dp_soc_be *be_partner_soc; 144 uint8_t pool_id; 145 QDF_STATUS qdf_status = QDF_STATUS_SUCCESS; 146 147 for (i = 0; i < WLAN_MAX_MLO_CHIPS; i++) { 148 partner_soc = dp_mlo_get_soc_ref_by_chip_id(mlo_ctxt, i); 149 if (!partner_soc) { 150 dp_err("partner_soc is NULL"); 151 continue; 152 } 153 154 be_partner_soc = dp_get_be_soc_from_dp_soc(partner_soc); 155 156 for (pool_id = 0; pool_id < MAX_RXDESC_POOLS; pool_id++) { 157 qdf_status = 158 dp_hw_cookie_conversion_init 159 (be_soc, 160 &be_partner_soc->rx_cc_ctx[pool_id]); 161 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { 162 dp_alert("MLO partner soc RX CC init failed"); 163 return qdf_status; 164 } 165 } 166 } 167 168 return qdf_status; 169 } 170 171 static void dp_mlo_soc_setup(struct cdp_soc_t *soc_hdl, 172 struct cdp_mlo_ctxt *cdp_ml_ctxt) 173 { 174 struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); 175 struct dp_mlo_ctxt *mlo_ctxt = cdp_mlo_ctx_to_dp(cdp_ml_ctxt); 176 struct dp_soc_be *be_soc = dp_get_be_soc_from_dp_soc(soc); 177 178 if (!cdp_ml_ctxt) 179 return; 180 181 dp_mlo_set_soc_by_chip_id(mlo_ctxt, soc, be_soc->mlo_chip_id); 182 } 183 184 static void dp_mlo_soc_teardown(struct cdp_soc_t *soc_hdl, 185 struct cdp_mlo_ctxt *cdp_ml_ctxt) 186 { 187 struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); 188 struct dp_mlo_ctxt *mlo_ctxt = cdp_mlo_ctx_to_dp(cdp_ml_ctxt); 189 struct dp_soc_be *be_soc = dp_get_be_soc_from_dp_soc(soc); 190 191 if (!cdp_ml_ctxt) 192 return; 193 194 dp_mlo_set_soc_by_chip_id(mlo_ctxt, NULL, be_soc->mlo_chip_id); 195 } 196 197 static QDF_STATUS dp_mlo_add_ptnr_vdev(struct dp_vdev *vdev1, 198 struct dp_vdev *vdev2, 199 struct dp_soc *soc, uint8_t pdev_id) 200 { 201 struct dp_soc_be *soc_be = dp_get_be_soc_from_dp_soc(soc); 202 struct dp_vdev_be *vdev2_be = dp_get_be_vdev_from_dp_vdev(vdev2); 203 204 /* return when valid entry exists */ 205 if (vdev2_be->partner_vdev_list[soc_be->mlo_chip_id][pdev_id] != 206 CDP_INVALID_VDEV_ID) 207 return QDF_STATUS_SUCCESS; 208 209 if (dp_vdev_get_ref(soc, vdev1, DP_MOD_ID_RX) != 210 QDF_STATUS_SUCCESS) { 211 qdf_info("%pK: unable to get vdev reference vdev %pK vdev_id %u", 212 soc, vdev1, vdev1->vdev_id); 213 return QDF_STATUS_E_FAILURE; 214 } 215 216 vdev2_be->partner_vdev_list[soc_be->mlo_chip_id][pdev_id] = 217 vdev1->vdev_id; 218 219 mlo_debug("Add vdev%d to vdev%d list, mlo_chip_id = %d pdev_id = %d\n", 220 vdev1->vdev_id, vdev2->vdev_id, soc_be->mlo_chip_id, pdev_id); 221 222 return QDF_STATUS_SUCCESS; 223 } 224 225 QDF_STATUS dp_update_mlo_ptnr_list(struct cdp_soc_t *soc_hdl, 226 int8_t partner_vdev_ids[], uint8_t num_vdevs, 227 uint8_t self_vdev_id) 228 { 229 int i, j; 230 struct dp_soc *self_soc = cdp_soc_t_to_dp_soc(soc_hdl); 231 struct dp_vdev *self_vdev; 232 QDF_STATUS ret = QDF_STATUS_SUCCESS; 233 struct dp_soc_be *be_soc = dp_get_be_soc_from_dp_soc(self_soc); 234 struct dp_mlo_ctxt *dp_mlo = be_soc->ml_ctxt; 235 236 if (!dp_mlo) 237 return QDF_STATUS_E_FAILURE; 238 239 self_vdev = dp_vdev_get_ref_by_id(self_soc, self_vdev_id, DP_MOD_ID_RX); 240 if (!self_vdev) 241 return QDF_STATUS_E_FAILURE; 242 243 /* go through the input vdev id list and if there are partner vdevs, 244 * - then add the current vdev's id to partner vdev's list using pdev_id and 245 * increase the reference 246 * - add partner vdev to self list and increase the reference 247 */ 248 for (i = 0; i < num_vdevs; i++) { 249 if (partner_vdev_ids[i] == CDP_INVALID_VDEV_ID) 250 continue; 251 252 for (j = 0; j < WLAN_MAX_MLO_CHIPS; j++) { 253 struct dp_soc *soc = 254 dp_mlo_get_soc_ref_by_chip_id(dp_mlo, j); 255 if (soc) { 256 struct dp_vdev *vdev; 257 258 vdev = dp_vdev_get_ref_by_id(soc, 259 partner_vdev_ids[i], DP_MOD_ID_RX); 260 if (vdev) { 261 if (vdev == self_vdev) { 262 dp_vdev_unref_delete(soc, 263 vdev, DP_MOD_ID_RX); 264 /*dp_soc_unref_delete(soc); */ 265 continue; 266 } 267 if (qdf_is_macaddr_equal( 268 (struct qdf_mac_addr *)self_vdev->mld_mac_addr.raw, 269 (struct qdf_mac_addr *)vdev->mld_mac_addr.raw)) { 270 if (dp_mlo_add_ptnr_vdev(self_vdev, 271 vdev, self_soc, 272 self_vdev->pdev->pdev_id) != 273 QDF_STATUS_SUCCESS) { 274 dp_err("Unable to add self to partner vdev's list"); 275 dp_vdev_unref_delete(soc, 276 vdev, DP_MOD_ID_RX); 277 /* TODO - release soc ref here */ 278 /* dp_soc_unref_delete(soc);*/ 279 ret = QDF_STATUS_E_FAILURE; 280 goto exit; 281 } 282 /* add to self list */ 283 if (dp_mlo_add_ptnr_vdev(vdev, self_vdev, soc, 284 vdev->pdev->pdev_id) != 285 QDF_STATUS_SUCCESS) { 286 dp_err("Unable to add vdev to self vdev's list"); 287 dp_vdev_unref_delete(self_soc, 288 vdev, DP_MOD_ID_RX); 289 /* TODO - release soc ref here */ 290 /* dp_soc_unref_delete(soc);*/ 291 ret = QDF_STATUS_E_FAILURE; 292 goto exit; 293 } 294 } 295 dp_vdev_unref_delete(soc, vdev, 296 DP_MOD_ID_RX); 297 } /* vdev */ 298 /* TODO - release soc ref here */ 299 /* dp_soc_unref_delete(soc); */ 300 } /* soc */ 301 } /* for */ 302 } /* for */ 303 304 exit: 305 dp_vdev_unref_delete(self_soc, self_vdev, DP_MOD_ID_RX); 306 return ret; 307 } 308 309 void dp_clr_mlo_ptnr_list(struct dp_soc *soc, struct dp_vdev *vdev) 310 { 311 struct dp_soc_be *be_soc = dp_get_be_soc_from_dp_soc(soc); 312 struct dp_vdev_be *vdev_be = dp_get_be_vdev_from_dp_vdev(vdev); 313 struct dp_mlo_ctxt *dp_mlo = be_soc->ml_ctxt; 314 uint8_t soc_id = be_soc->mlo_chip_id; 315 uint8_t pdev_id = vdev->pdev->pdev_id; 316 int i, j; 317 318 for (i = 0; i < WLAN_MAX_MLO_CHIPS; i++) { 319 for (j = 0; j < WLAN_MAX_MLO_LINKS_PER_SOC; j++) { 320 struct dp_vdev *pr_vdev; 321 struct dp_soc *pr_soc; 322 struct dp_soc_be *pr_soc_be; 323 struct dp_pdev *pr_pdev; 324 struct dp_vdev_be *pr_vdev_be; 325 326 if (vdev_be->partner_vdev_list[i][j] == 327 CDP_INVALID_VDEV_ID) 328 continue; 329 330 pr_soc = dp_mlo_get_soc_ref_by_chip_id(dp_mlo, i); 331 if (!pr_soc) 332 continue; 333 pr_soc_be = dp_get_be_soc_from_dp_soc(pr_soc); 334 pr_vdev = dp_vdev_get_ref_by_id(pr_soc, 335 vdev_be->partner_vdev_list[i][j], 336 DP_MOD_ID_RX); 337 if (!pr_vdev) 338 continue; 339 340 /* release ref and remove self vdev from partner list */ 341 pr_vdev_be = dp_get_be_vdev_from_dp_vdev(pr_vdev); 342 dp_vdev_unref_delete(soc, vdev, DP_MOD_ID_RX); 343 pr_vdev_be->partner_vdev_list[soc_id][pdev_id] = 344 CDP_INVALID_VDEV_ID; 345 346 /* release ref and remove partner vdev from self list */ 347 dp_vdev_unref_delete(pr_soc, pr_vdev, DP_MOD_ID_RX); 348 pr_pdev = pr_vdev->pdev; 349 vdev_be->partner_vdev_list[pr_soc_be->mlo_chip_id][pr_pdev->pdev_id] = 350 CDP_INVALID_VDEV_ID; 351 352 dp_vdev_unref_delete(pr_soc, pr_vdev, DP_MOD_ID_RX); 353 } 354 } 355 } 356 357 static void dp_mlo_setup_complete(struct cdp_mlo_ctxt *cdp_ml_ctxt) 358 { 359 struct dp_mlo_ctxt *mlo_ctxt = cdp_mlo_ctx_to_dp(cdp_ml_ctxt); 360 int i; 361 struct dp_soc *soc; 362 struct dp_soc_be *be_soc; 363 QDF_STATUS qdf_status; 364 365 if (!cdp_ml_ctxt) 366 return; 367 368 for (i = 0; i < WLAN_MAX_MLO_CHIPS; i++) { 369 soc = dp_mlo_get_soc_ref_by_chip_id(mlo_ctxt, i); 370 371 if (!soc) 372 continue; 373 be_soc = dp_get_be_soc_from_dp_soc(soc); 374 375 qdf_status = dp_partner_soc_rx_hw_cc_init(mlo_ctxt, be_soc); 376 377 if (!QDF_IS_STATUS_SUCCESS(qdf_status)) { 378 dp_alert("MLO partner SOC Rx desc CC init failed"); 379 qdf_assert_always(0); 380 } 381 } 382 } 383 384 static void dp_mlo_update_delta_tsf2(struct cdp_soc_t *soc_hdl, 385 uint8_t pdev_id, uint64_t delta_tsf2) 386 { 387 struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); 388 struct dp_pdev *pdev; 389 struct dp_pdev_be *be_pdev; 390 391 pdev = dp_get_pdev_from_soc_pdev_id_wifi3((struct dp_soc *)soc, 392 pdev_id); 393 if (!pdev) { 394 dp_err("pdev is NULL for pdev_id %u", pdev_id); 395 return; 396 } 397 398 be_pdev = dp_get_be_pdev_from_dp_pdev(pdev); 399 400 be_pdev->delta_tsf2 = delta_tsf2; 401 } 402 403 static void dp_mlo_update_delta_tqm(struct cdp_soc_t *soc_hdl, 404 uint64_t delta_tqm) 405 { 406 struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); 407 struct dp_soc_be *be_soc = dp_get_be_soc_from_dp_soc(soc); 408 409 be_soc->delta_tqm = delta_tqm; 410 } 411 412 static void dp_mlo_update_mlo_ts_offset(struct cdp_soc_t *soc_hdl, 413 uint64_t offset) 414 { 415 struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl); 416 struct dp_soc_be *be_soc = dp_get_be_soc_from_dp_soc(soc); 417 418 be_soc->mlo_tstamp_offset = offset; 419 } 420 421 static struct cdp_mlo_ops dp_mlo_ops = { 422 .mlo_soc_setup = dp_mlo_soc_setup, 423 .mlo_soc_teardown = dp_mlo_soc_teardown, 424 .update_mlo_ptnr_list = dp_update_mlo_ptnr_list, 425 .mlo_setup_complete = dp_mlo_setup_complete, 426 .mlo_update_delta_tsf2 = dp_mlo_update_delta_tsf2, 427 .mlo_update_delta_tqm = dp_mlo_update_delta_tqm, 428 .mlo_update_mlo_ts_offset = dp_mlo_update_mlo_ts_offset, 429 }; 430 431 void dp_soc_mlo_fill_params(struct dp_soc *soc, 432 struct cdp_soc_attach_params *params) 433 { 434 struct dp_soc_be *be_soc = dp_get_be_soc_from_dp_soc(soc); 435 436 if (!params->mlo_enabled) { 437 dp_warn("MLO not enabled on SOC"); 438 return; 439 } 440 441 be_soc->mlo_chip_id = params->mlo_chip_id; 442 be_soc->ml_ctxt = cdp_mlo_ctx_to_dp(params->ml_context); 443 be_soc->mlo_enabled = 1; 444 soc->cdp_soc.ops->mlo_ops = &dp_mlo_ops; 445 } 446 447 void dp_mlo_update_link_to_pdev_map(struct dp_soc *soc, struct dp_pdev *pdev) 448 { 449 struct dp_soc_be *be_soc = dp_get_be_soc_from_dp_soc(soc); 450 struct dp_pdev_be *be_pdev = dp_get_be_pdev_from_dp_pdev(pdev); 451 struct dp_mlo_ctxt *ml_ctxt = be_soc->ml_ctxt; 452 uint8_t link_id; 453 454 if (!be_soc->mlo_enabled) 455 return; 456 457 if (!ml_ctxt) 458 return; 459 460 link_id = be_pdev->mlo_link_id; 461 462 if (link_id < WLAN_MAX_MLO_CHIPS * WLAN_MAX_MLO_LINKS_PER_SOC) { 463 if (!ml_ctxt->link_to_pdev_map[link_id]) 464 ml_ctxt->link_to_pdev_map[link_id] = be_pdev; 465 else 466 dp_alert("Attempt to update existing map for link %u", 467 link_id); 468 } 469 } 470 471 void dp_mlo_update_link_to_pdev_unmap(struct dp_soc *soc, struct dp_pdev *pdev) 472 { 473 struct dp_soc_be *be_soc = dp_get_be_soc_from_dp_soc(soc); 474 struct dp_pdev_be *be_pdev = dp_get_be_pdev_from_dp_pdev(pdev); 475 struct dp_mlo_ctxt *ml_ctxt = be_soc->ml_ctxt; 476 uint8_t link_id; 477 478 if (!be_soc->mlo_enabled) 479 return; 480 481 if (!ml_ctxt) 482 return; 483 484 link_id = be_pdev->mlo_link_id; 485 486 if (link_id < WLAN_MAX_MLO_CHIPS * WLAN_MAX_MLO_LINKS_PER_SOC) 487 ml_ctxt->link_to_pdev_map[link_id] = NULL; 488 } 489 490 static struct dp_pdev_be * 491 dp_mlo_get_be_pdev_from_link_id(struct dp_mlo_ctxt *ml_ctxt, uint8_t link_id) 492 { 493 if (link_id < WLAN_MAX_MLO_CHIPS * WLAN_MAX_MLO_LINKS_PER_SOC) 494 return ml_ctxt->link_to_pdev_map[link_id]; 495 return NULL; 496 } 497 498 void dp_pdev_mlo_fill_params(struct dp_pdev *pdev, 499 struct cdp_pdev_attach_params *params) 500 { 501 struct dp_soc_be *be_soc = dp_get_be_soc_from_dp_soc(pdev->soc); 502 struct dp_pdev_be *be_pdev = dp_get_be_pdev_from_dp_pdev(pdev); 503 504 if (!be_soc->mlo_enabled) { 505 dp_info("MLO not enabled on SOC"); 506 return; 507 } 508 509 be_pdev->mlo_link_id = params->mlo_link_id; 510 } 511 512 void dp_mlo_partner_chips_map(struct dp_soc *soc, 513 struct dp_peer *peer, 514 uint16_t peer_id) 515 { 516 struct dp_soc_be *be_soc = dp_get_be_soc_from_dp_soc(soc); 517 struct dp_mlo_ctxt *mlo_ctxt = NULL; 518 bool is_ml_peer_id = 519 HTT_RX_PEER_META_DATA_V1_ML_PEER_VALID_GET(peer_id); 520 uint8_t chip_id; 521 struct dp_soc *temp_soc; 522 523 /* for non ML peer dont map on partner chips*/ 524 if (!is_ml_peer_id) 525 return; 526 527 mlo_ctxt = be_soc->ml_ctxt; 528 if (!mlo_ctxt) 529 return; 530 531 qdf_spin_lock_bh(&mlo_ctxt->ml_soc_list_lock); 532 for (chip_id = 0; chip_id < DP_MAX_MLO_CHIPS; chip_id++) { 533 temp_soc = mlo_ctxt->ml_soc_list[chip_id]; 534 535 if (!temp_soc) 536 continue; 537 538 /* skip if this is current soc */ 539 if (temp_soc == soc) 540 continue; 541 542 dp_peer_find_id_to_obj_add(temp_soc, peer, peer_id); 543 } 544 qdf_spin_unlock_bh(&mlo_ctxt->ml_soc_list_lock); 545 } 546 547 qdf_export_symbol(dp_mlo_partner_chips_map); 548 549 void dp_mlo_partner_chips_unmap(struct dp_soc *soc, 550 uint16_t peer_id) 551 { 552 struct dp_soc_be *be_soc = dp_get_be_soc_from_dp_soc(soc); 553 struct dp_mlo_ctxt *mlo_ctxt = be_soc->ml_ctxt; 554 bool is_ml_peer_id = 555 HTT_RX_PEER_META_DATA_V1_ML_PEER_VALID_GET(peer_id); 556 uint8_t chip_id; 557 struct dp_soc *temp_soc; 558 559 if (!is_ml_peer_id) 560 return; 561 562 if (!mlo_ctxt) 563 return; 564 565 qdf_spin_lock_bh(&mlo_ctxt->ml_soc_list_lock); 566 for (chip_id = 0; chip_id < DP_MAX_MLO_CHIPS; chip_id++) { 567 temp_soc = mlo_ctxt->ml_soc_list[chip_id]; 568 569 if (!temp_soc) 570 continue; 571 572 /* skip if this is current soc */ 573 if (temp_soc == soc) 574 continue; 575 576 dp_peer_find_id_to_obj_remove(temp_soc, peer_id); 577 } 578 qdf_spin_unlock_bh(&mlo_ctxt->ml_soc_list_lock); 579 } 580 581 qdf_export_symbol(dp_mlo_partner_chips_unmap); 582 583 uint8_t dp_mlo_get_chip_id(struct dp_soc *soc) 584 { 585 struct dp_soc_be *be_soc = dp_get_be_soc_from_dp_soc(soc); 586 587 return be_soc->mlo_chip_id; 588 } 589 590 qdf_export_symbol(dp_mlo_get_chip_id); 591 592 struct dp_peer * 593 dp_link_peer_hash_find_by_chip_id(struct dp_soc *soc, 594 uint8_t *peer_mac_addr, 595 int mac_addr_is_aligned, 596 uint8_t vdev_id, 597 uint8_t chip_id, 598 enum dp_mod_id mod_id) 599 { 600 struct dp_soc_be *be_soc = dp_get_be_soc_from_dp_soc(soc); 601 struct dp_mlo_ctxt *mlo_ctxt = be_soc->ml_ctxt; 602 struct dp_soc *link_peer_soc = NULL; 603 struct dp_peer *peer = NULL; 604 605 if (!mlo_ctxt) 606 return NULL; 607 608 link_peer_soc = dp_mlo_get_soc_ref_by_chip_id(mlo_ctxt, chip_id); 609 610 if (!link_peer_soc) 611 return NULL; 612 613 peer = dp_peer_find_hash_find(link_peer_soc, peer_mac_addr, 614 mac_addr_is_aligned, vdev_id, 615 mod_id); 616 qdf_atomic_dec(&link_peer_soc->ref_count); 617 return peer; 618 } 619 620 qdf_export_symbol(dp_link_peer_hash_find_by_chip_id); 621 622 void dp_mlo_get_rx_hash_key(struct dp_soc *soc, 623 struct cdp_lro_hash_config *lro_hash) 624 { 625 struct dp_soc_be *be_soc = dp_get_be_soc_from_dp_soc(soc); 626 struct dp_mlo_ctxt *ml_ctxt = be_soc->ml_ctxt; 627 628 if (!be_soc->mlo_enabled || !ml_ctxt) 629 return dp_get_rx_hash_key_bytes(lro_hash); 630 631 qdf_mem_copy(lro_hash->toeplitz_hash_ipv4, ml_ctxt->toeplitz_hash_ipv4, 632 (sizeof(lro_hash->toeplitz_hash_ipv4[0]) * 633 LRO_IPV4_SEED_ARR_SZ)); 634 qdf_mem_copy(lro_hash->toeplitz_hash_ipv6, ml_ctxt->toeplitz_hash_ipv6, 635 (sizeof(lro_hash->toeplitz_hash_ipv6[0]) * 636 LRO_IPV6_SEED_ARR_SZ)); 637 } 638 639 struct dp_soc * 640 dp_rx_replensih_soc_get(struct dp_soc *soc, uint8_t chip_id) 641 { 642 struct dp_soc_be *be_soc = dp_get_be_soc_from_dp_soc(soc); 643 struct dp_mlo_ctxt *mlo_ctxt = be_soc->ml_ctxt; 644 struct dp_soc *replenish_soc; 645 646 if (!be_soc->mlo_enabled || !mlo_ctxt) 647 return soc; 648 649 replenish_soc = dp_mlo_get_soc_ref_by_chip_id(mlo_ctxt, chip_id); 650 if (qdf_unlikely(!replenish_soc)) { 651 dp_alert("replenish SOC is NULL"); 652 qdf_assert_always(0); 653 } 654 655 return replenish_soc; 656 } 657 658 #ifdef WLAN_MCAST_MLO 659 void dp_mcast_mlo_iter_ptnr_soc(struct dp_soc_be *be_soc, 660 dp_ptnr_soc_iter_func func, 661 void *arg) 662 { 663 int i = 0; 664 struct dp_mlo_ctxt *dp_mlo = be_soc->ml_ctxt; 665 666 for (i = 0; i < WLAN_MAX_MLO_CHIPS ; i++) { 667 struct dp_soc *ptnr_soc = 668 dp_mlo_get_soc_ref_by_chip_id(dp_mlo, i); 669 670 if (!ptnr_soc) 671 continue; 672 (*func)(ptnr_soc, arg); 673 } 674 } 675 676 qdf_export_symbol(dp_mcast_mlo_iter_ptnr_soc); 677 678 void dp_mcast_mlo_iter_ptnr_vdev(struct dp_soc_be *be_soc, 679 struct dp_vdev_be *be_vdev, 680 dp_ptnr_vdev_iter_func func, 681 void *arg, 682 enum dp_mod_id mod_id) 683 { 684 int i = 0; 685 int j = 0; 686 struct dp_mlo_ctxt *dp_mlo = be_soc->ml_ctxt; 687 688 for (i = 0; i < WLAN_MAX_MLO_CHIPS ; i++) { 689 struct dp_soc *ptnr_soc = 690 dp_mlo_get_soc_ref_by_chip_id(dp_mlo, i); 691 692 if (!ptnr_soc) 693 continue; 694 for (j = 0 ; j < WLAN_MAX_MLO_LINKS_PER_SOC ; j++) { 695 struct dp_vdev *ptnr_vdev; 696 697 ptnr_vdev = dp_vdev_get_ref_by_id( 698 ptnr_soc, 699 be_vdev->partner_vdev_list[i][j], 700 mod_id); 701 if (!ptnr_vdev) 702 continue; 703 (*func)(be_vdev, ptnr_vdev, arg); 704 dp_vdev_unref_delete(ptnr_vdev->pdev->soc, 705 ptnr_vdev, 706 mod_id); 707 } 708 } 709 } 710 711 qdf_export_symbol(dp_mcast_mlo_iter_ptnr_vdev); 712 713 struct dp_vdev *dp_mlo_get_mcast_primary_vdev(struct dp_soc_be *be_soc, 714 struct dp_vdev_be *be_vdev, 715 enum dp_mod_id mod_id) 716 { 717 int i = 0; 718 int j = 0; 719 struct dp_mlo_ctxt *dp_mlo = be_soc->ml_ctxt; 720 721 for (i = 0; i < WLAN_MAX_MLO_CHIPS ; i++) { 722 struct dp_soc *ptnr_soc = 723 dp_mlo_get_soc_ref_by_chip_id(dp_mlo, i); 724 725 if (!ptnr_soc) 726 continue; 727 for (j = 0 ; j < WLAN_MAX_MLO_LINKS_PER_SOC ; j++) { 728 struct dp_vdev *ptnr_vdev = NULL; 729 struct dp_vdev_be *be_ptnr_vdev = NULL; 730 731 ptnr_vdev = dp_vdev_get_ref_by_id( 732 ptnr_soc, 733 be_vdev->partner_vdev_list[i][j], 734 mod_id); 735 if (!ptnr_vdev) 736 continue; 737 be_ptnr_vdev = dp_get_be_vdev_from_dp_vdev(ptnr_vdev); 738 if (be_ptnr_vdev->mcast_primary) 739 return ptnr_vdev; 740 dp_vdev_unref_delete(be_ptnr_vdev->vdev.pdev->soc, 741 &be_ptnr_vdev->vdev, 742 mod_id); 743 } 744 } 745 return NULL; 746 } 747 748 qdf_export_symbol(dp_mlo_get_mcast_primary_vdev); 749 #endif 750 751 static inline uint64_t dp_mlo_get_mlo_ts_offset(struct dp_pdev_be *be_pdev) 752 { 753 struct dp_soc *soc; 754 struct dp_pdev *pdev; 755 struct dp_soc_be *be_soc; 756 uint32_t mlo_offset; 757 758 pdev = &be_pdev->pdev; 759 soc = pdev->soc; 760 be_soc = dp_get_be_soc_from_dp_soc(soc); 761 762 mlo_offset = be_soc->mlo_tstamp_offset; 763 764 return mlo_offset; 765 } 766 767 int32_t dp_mlo_get_delta_tsf2_wrt_mlo_offset(struct dp_soc *soc, 768 uint8_t hw_link_id) 769 { 770 struct dp_soc_be *be_soc = dp_get_be_soc_from_dp_soc(soc); 771 struct dp_mlo_ctxt *ml_ctxt = be_soc->ml_ctxt; 772 struct dp_pdev_be *be_pdev; 773 int32_t delta_tsf2_mlo_offset; 774 int32_t mlo_offset, delta_tsf2; 775 776 if (!ml_ctxt) 777 return 0; 778 779 be_pdev = dp_mlo_get_be_pdev_from_link_id(ml_ctxt, hw_link_id); 780 if (!be_pdev) 781 return 0; 782 783 mlo_offset = dp_mlo_get_mlo_ts_offset(be_pdev); 784 delta_tsf2 = be_pdev->delta_tsf2; 785 786 delta_tsf2_mlo_offset = mlo_offset - delta_tsf2; 787 788 return delta_tsf2_mlo_offset; 789 } 790 791 int32_t dp_mlo_get_delta_tqm_wrt_mlo_offset(struct dp_soc *soc) 792 { 793 struct dp_soc_be *be_soc = dp_get_be_soc_from_dp_soc(soc); 794 int32_t delta_tqm_mlo_offset; 795 int32_t mlo_offset, delta_tqm; 796 797 mlo_offset = be_soc->mlo_tstamp_offset; 798 delta_tqm = be_soc->delta_tqm; 799 800 delta_tqm_mlo_offset = mlo_offset - delta_tqm; 801 802 return delta_tqm_mlo_offset; 803 } 804