1 /* 2 * Copyright (c) 2021, The Linux Foundation. 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 17 #include "wlan_mlo_mgr_main.h" 18 #include "qdf_types.h" 19 #include "wlan_cmn.h" 20 #include <include/wlan_vdev_mlme.h> 21 #include "wlan_mlo_mgr_ap.h" 22 #include "wlan_mlo_mgr_cmn.h" 23 24 static void mlo_peer_set_aid_bit(struct wlan_ml_vdev_aid_mgr *ml_aid_mgr, 25 uint16_t assoc_id_ix) 26 { 27 uint16_t ix; 28 struct wlan_vdev_aid_mgr *vdev_aid_mgr; 29 30 /* Mark this bit as AID assigned */ 31 for (ix = 0; ix < WLAN_UMAC_MLO_MAX_VDEVS; ix++) { 32 vdev_aid_mgr = ml_aid_mgr->aid_mgr[ix]; 33 if (vdev_aid_mgr) 34 qdf_set_bit(assoc_id_ix, vdev_aid_mgr->aid_bitmap); 35 } 36 } 37 38 static uint16_t wlan_mlo_peer_alloc_aid( 39 struct wlan_ml_vdev_aid_mgr *ml_aid_mgr, 40 bool is_mlo_peer, 41 uint8_t link_ix) 42 { 43 uint16_t assoc_id = (uint16_t)-1; 44 uint16_t i, j; 45 struct wlan_vdev_aid_mgr *vdev_aid_mgr; 46 uint16_t first_aid = 0; 47 struct mlo_mgr_context *mlo_mgr_ctx = wlan_objmgr_get_mlo_ctx(); 48 49 if (!mlo_mgr_ctx) 50 return assoc_id; 51 52 if (!is_mlo_peer && link_ix == MLO_INVALID_LINK_IDX) 53 return assoc_id; 54 /* TODO check locking strategy */ 55 ml_aid_lock_acquire(mlo_mgr_ctx); 56 57 for (i = 0; i < ml_aid_mgr->max_aid; i++) { 58 if (qdf_test_bit(i, ml_aid_mgr->aid_bitmap)) 59 continue; 60 61 if (is_mlo_peer) { 62 for (j = 0; j < WLAN_UMAC_MLO_MAX_VDEVS; j++) { 63 vdev_aid_mgr = ml_aid_mgr->aid_mgr[j]; 64 if (vdev_aid_mgr && 65 qdf_test_bit(i, vdev_aid_mgr->aid_bitmap)) 66 break; 67 /* AID is free */ 68 if (j == WLAN_UMAC_MLO_MAX_VDEVS - 1) { 69 assoc_id = i + 1; 70 mlo_peer_set_aid_bit(ml_aid_mgr, i); 71 } 72 } 73 74 if (assoc_id == i + 1) { 75 qdf_set_bit(i, ml_aid_mgr->aid_bitmap); 76 break; 77 } 78 } else { 79 vdev_aid_mgr = ml_aid_mgr->aid_mgr[link_ix]; 80 if (vdev_aid_mgr) 81 break; 82 83 if (qdf_test_bit(i, vdev_aid_mgr->aid_bitmap)) 84 continue; 85 86 if (!first_aid) 87 first_aid = i + 1; 88 89 for (j = 0; j < WLAN_UMAC_MLO_MAX_VDEVS; j++) { 90 if (j == link_ix) 91 continue; 92 93 vdev_aid_mgr = ml_aid_mgr->aid_mgr[j]; 94 if (vdev_aid_mgr && 95 qdf_test_bit(i, vdev_aid_mgr->aid_bitmap)) { 96 assoc_id = i + 1; 97 break; 98 } 99 } 100 if (assoc_id == i + 1) { 101 vdev_aid_mgr = ml_aid_mgr->aid_mgr[link_ix]; 102 qdf_set_bit(i, vdev_aid_mgr->aid_bitmap); 103 first_aid = 0; 104 break; 105 } 106 } 107 } 108 109 if ((!is_mlo_peer) && first_aid) { 110 vdev_aid_mgr = ml_aid_mgr->aid_mgr[link_ix]; 111 qdf_set_bit(first_aid, vdev_aid_mgr->aid_bitmap); 112 assoc_id = first_aid; 113 } 114 115 ml_aid_lock_release(mlo_mgr_ctx); 116 117 return assoc_id; 118 } 119 120 static uint16_t wlan_mlme_peer_alloc_aid( 121 struct wlan_vdev_aid_mgr *vdev_aid_mgr, 122 bool no_lock) 123 { 124 uint16_t assoc_id = (uint16_t)-1; 125 uint16_t i; 126 struct mlo_mgr_context *mlo_mgr_ctx = wlan_objmgr_get_mlo_ctx(); 127 128 if (!mlo_mgr_ctx) 129 return assoc_id; 130 131 if (!no_lock) 132 ml_aid_lock_acquire(mlo_mgr_ctx); 133 134 for (i = 0; i < vdev_aid_mgr->max_aid; i++) { 135 if (qdf_test_bit(i, vdev_aid_mgr->aid_bitmap)) 136 continue; 137 138 assoc_id = i + 1; 139 qdf_set_bit(i, vdev_aid_mgr->aid_bitmap); 140 } 141 142 if (!no_lock) 143 ml_aid_lock_release(mlo_mgr_ctx); 144 145 return assoc_id; 146 } 147 148 QDF_STATUS wlan_mlo_peer_free_aid( 149 struct wlan_ml_vdev_aid_mgr *ml_aid_mgr, 150 uint8_t link_ix, 151 uint16_t assoc_id) 152 { 153 uint16_t j; 154 struct wlan_vdev_aid_mgr *vdev_aid_mgr; 155 struct mlo_mgr_context *mlo_mgr_ctx = wlan_objmgr_get_mlo_ctx(); 156 uint16_t assoc_id_ix; 157 158 if (!mlo_mgr_ctx) 159 return QDF_STATUS_E_FAILURE; 160 161 /* TODO check locking strategy */ 162 ml_aid_lock_acquire(mlo_mgr_ctx); 163 assoc_id_ix = assoc_id - 1; 164 if (qdf_test_bit(assoc_id_ix, ml_aid_mgr->aid_bitmap)) { 165 qdf_clear_bit(assoc_id_ix, ml_aid_mgr->aid_bitmap); 166 for (j = 0; j < WLAN_UMAC_MLO_MAX_VDEVS; j++) { 167 vdev_aid_mgr = ml_aid_mgr->aid_mgr[j]; 168 if (vdev_aid_mgr && 169 qdf_test_bit(assoc_id_ix, 170 vdev_aid_mgr->aid_bitmap)) { 171 qdf_clear_bit(assoc_id_ix, 172 vdev_aid_mgr->aid_bitmap); 173 } 174 } 175 } else { 176 vdev_aid_mgr = ml_aid_mgr->aid_mgr[link_ix]; 177 if (vdev_aid_mgr) 178 qdf_clear_bit(assoc_id_ix, vdev_aid_mgr->aid_bitmap); 179 } 180 181 ml_aid_lock_release(mlo_mgr_ctx); 182 183 return QDF_STATUS_SUCCESS; 184 } 185 186 void wlan_mlme_peer_free_aid( 187 struct wlan_vdev_aid_mgr *vdev_aid_mgr, 188 bool no_lock, uint16_t assoc_id) 189 { 190 struct mlo_mgr_context *mlo_mgr_ctx = wlan_objmgr_get_mlo_ctx(); 191 192 if (!mlo_mgr_ctx) 193 return; 194 195 if (!no_lock) 196 ml_aid_lock_acquire(mlo_mgr_ctx); 197 198 qdf_clear_bit(assoc_id - 1, vdev_aid_mgr->aid_bitmap); 199 200 if (!no_lock) 201 ml_aid_lock_release(mlo_mgr_ctx); 202 } 203 204 QDF_STATUS mlo_peer_allocate_aid( 205 struct wlan_mlo_dev_context *ml_dev, 206 struct wlan_mlo_peer_context *ml_peer) 207 { 208 uint16_t assoc_id = (uint16_t)-1; 209 struct wlan_ml_vdev_aid_mgr *ml_aid_mgr; 210 211 ml_aid_mgr = ml_dev->ap_ctx->ml_aid_mgr; 212 if (!ml_aid_mgr) 213 return QDF_STATUS_E_INVAL; 214 215 assoc_id = wlan_mlo_peer_alloc_aid(ml_aid_mgr, true, 0xff); 216 if (assoc_id == (uint16_t)-1) 217 return QDF_STATUS_E_NOENT; 218 219 ml_peer->assoc_id = assoc_id; 220 221 return QDF_STATUS_SUCCESS; 222 } 223 224 QDF_STATUS mlo_peer_free_aid(struct wlan_mlo_dev_context *ml_dev, 225 struct wlan_mlo_peer_context *ml_peer) 226 { 227 struct wlan_ml_vdev_aid_mgr *ml_aid_mgr; 228 QDF_STATUS status = QDF_STATUS_SUCCESS; 229 230 ml_aid_mgr = ml_dev->ap_ctx->ml_aid_mgr; 231 if (!ml_aid_mgr) 232 return QDF_STATUS_E_INVAL; 233 234 wlan_mlo_peer_free_aid(ml_aid_mgr, 0xff, ml_peer->assoc_id); 235 236 return status; 237 } 238 239 uint16_t mlo_get_aid(struct wlan_objmgr_vdev *vdev) 240 { 241 struct wlan_mlo_dev_context *ml_dev; 242 uint16_t assoc_id = (uint16_t)-1; 243 struct wlan_ml_vdev_aid_mgr *ml_aid_mgr; 244 245 ml_dev = vdev->mlo_dev_ctx; 246 247 if (!ml_dev) 248 return assoc_id; 249 250 ml_aid_mgr = ml_dev->ap_ctx->ml_aid_mgr; 251 if (!ml_aid_mgr) 252 return assoc_id; 253 254 return wlan_mlo_peer_alloc_aid(ml_aid_mgr, true, 0xff); 255 } 256 257 QDF_STATUS mlo_free_aid(struct wlan_objmgr_vdev *vdev, uint16_t assoc_id) 258 { 259 struct wlan_mlo_dev_context *ml_dev; 260 struct wlan_ml_vdev_aid_mgr *ml_aid_mgr; 261 262 ml_dev = vdev->mlo_dev_ctx; 263 264 if (!ml_dev) 265 return QDF_STATUS_E_INVAL; 266 267 ml_aid_mgr = ml_dev->ap_ctx->ml_aid_mgr; 268 if (!ml_aid_mgr) 269 return QDF_STATUS_E_INVAL; 270 271 return wlan_mlo_peer_free_aid(ml_aid_mgr, true, assoc_id); 272 } 273 274 uint16_t mlme_get_aid(struct wlan_objmgr_vdev *vdev) 275 { 276 struct wlan_mlo_dev_context *ml_dev; 277 uint16_t assoc_id = (uint16_t)-1; 278 struct wlan_ml_vdev_aid_mgr *ml_aid_mgr; 279 struct wlan_vdev_aid_mgr *vdev_aid_mgr; 280 bool no_lock = true; 281 uint8_t link_id; 282 283 ml_dev = vdev->mlo_dev_ctx; 284 285 if (!ml_dev) { 286 vdev_aid_mgr = wlan_vdev_mlme_get_aid_mgr(vdev); 287 if (vdev_aid_mgr) { 288 if (qdf_atomic_read(&vdev_aid_mgr->ref_cnt) > 1) 289 no_lock = false; 290 return wlan_mlme_peer_alloc_aid(vdev_aid_mgr, no_lock); 291 } 292 return assoc_id; 293 } 294 295 ml_aid_mgr = ml_dev->ap_ctx->ml_aid_mgr; 296 if (!ml_aid_mgr) 297 return assoc_id; 298 299 link_id = mlo_get_link_vdev_ix(ml_dev, vdev); 300 301 assoc_id = wlan_mlo_peer_alloc_aid(ml_aid_mgr, false, link_id); 302 303 return assoc_id; 304 } 305 306 void mlme_free_aid(struct wlan_objmgr_vdev *vdev, uint16_t assoc_id) 307 { 308 struct wlan_mlo_dev_context *ml_dev; 309 struct wlan_ml_vdev_aid_mgr *ml_aid_mgr; 310 struct wlan_vdev_aid_mgr *vdev_aid_mgr; 311 bool no_lock = true; 312 uint8_t link_id; 313 314 ml_dev = vdev->mlo_dev_ctx; 315 316 if (!ml_dev) { 317 vdev_aid_mgr = wlan_vdev_mlme_get_aid_mgr(vdev); 318 if (vdev_aid_mgr) { 319 if (qdf_atomic_read(&vdev_aid_mgr->ref_cnt) > 1) 320 no_lock = false; 321 322 wlan_mlme_peer_free_aid(vdev_aid_mgr, no_lock, 323 assoc_id); 324 } 325 return; 326 } 327 328 ml_aid_mgr = ml_dev->ap_ctx->ml_aid_mgr; 329 if (!ml_aid_mgr) 330 return; 331 332 link_id = mlo_get_link_vdev_ix(ml_dev, vdev); 333 334 wlan_mlo_peer_free_aid(ml_aid_mgr, link_id, assoc_id); 335 } 336 337 struct wlan_vdev_aid_mgr *wlan_vdev_aid_mgr_init(uint16_t max_aid) 338 { 339 struct wlan_vdev_aid_mgr *aid_mgr; 340 341 aid_mgr = qdf_mem_malloc(sizeof(struct wlan_vdev_aid_mgr)); 342 if (!aid_mgr) 343 return NULL; 344 345 aid_mgr->max_aid = max_aid; 346 qdf_atomic_init(&aid_mgr->ref_cnt); 347 /* Take reference before returning */ 348 qdf_atomic_inc(&aid_mgr->ref_cnt); 349 350 return aid_mgr; 351 } 352 353 void wlan_vdev_aid_mgr_free(struct wlan_vdev_aid_mgr *aid_mgr) 354 { 355 if (!aid_mgr) 356 return; 357 358 if (!qdf_atomic_dec_and_test(&aid_mgr->ref_cnt)) 359 return; 360 361 aid_mgr->max_aid = 0; 362 qdf_mem_free(aid_mgr); 363 } 364 365 QDF_STATUS wlan_mlo_vdev_alloc_aid_mgr(struct wlan_mlo_dev_context *ml_dev, 366 struct wlan_objmgr_vdev *vdev) 367 { 368 uint8_t i; 369 uint8_t is_mbss_enabled = 0; 370 struct wlan_objmgr_vdev *vdev_iter; 371 struct wlan_objmgr_vdev *tx_vdev = NULL; 372 struct wlan_vdev_aid_mgr *aid_mgr; 373 struct wlan_ml_vdev_aid_mgr *ml_aidmgr; 374 uint16_t max_aid = WLAN_UMAC_MAX_AID; 375 376 if (!ml_dev->ap_ctx) { 377 mlo_err(" ML AP context is not initialized"); 378 QDF_BUG(0); 379 return QDF_STATUS_E_NOMEM; 380 } 381 ml_aidmgr = ml_dev->ap_ctx->ml_aid_mgr; 382 if (!ml_aidmgr) { 383 mlo_err(" ML AID mgr allocation failed"); 384 return QDF_STATUS_E_NOMEM; 385 } 386 387 for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) { 388 vdev_iter = ml_dev->wlan_vdev_list[i]; 389 if (!vdev_iter) 390 continue; 391 392 if (vdev != vdev_iter) 393 continue; 394 395 /* TODO */ 396 /* Get Tx VDEV, if VDEV is MBSSID */ 397 if (is_mbss_enabled) { 398 aid_mgr = wlan_vdev_mlme_get_aid_mgr(tx_vdev); 399 if (!aid_mgr) { 400 mlo_err("AID bitmap allocation failed for Tx VDEV%d", 401 wlan_vdev_get_id(tx_vdev)); 402 return QDF_STATUS_E_NOMEM; 403 } 404 qdf_atomic_inc(&aid_mgr->ref_cnt); 405 ml_aidmgr->aid_mgr[i] = aid_mgr; 406 wlan_vdev_mlme_set_aid_mgr(vdev, 407 ml_aidmgr->aid_mgr[i]); 408 break; 409 } else { 410 ml_aidmgr->aid_mgr[i] = wlan_vdev_aid_mgr_init(max_aid); 411 if (!ml_aidmgr->aid_mgr[i]) { 412 mlo_err("AID bitmap allocation failed for VDEV%d", 413 wlan_vdev_get_id(vdev)); 414 return QDF_STATUS_E_NOMEM; 415 } 416 wlan_vdev_mlme_set_aid_mgr(vdev, ml_aidmgr->aid_mgr[i]); 417 break; 418 } 419 } 420 421 return QDF_STATUS_SUCCESS; 422 } 423 424 QDF_STATUS wlan_mlo_vdev_free_aid_mgr(struct wlan_mlo_dev_context *ml_dev, 425 struct wlan_objmgr_vdev *vdev) 426 { 427 uint8_t i; 428 struct wlan_objmgr_vdev *vdev_iter; 429 struct wlan_ml_vdev_aid_mgr *ml_aidmgr; 430 431 if (!ml_dev->ap_ctx) { 432 mlo_err(" ML AP context is not initialized"); 433 QDF_BUG(0); 434 return QDF_STATUS_E_NOMEM; 435 } 436 ml_aidmgr = ml_dev->ap_ctx->ml_aid_mgr; 437 if (!ml_aidmgr) { 438 mlo_err(" ML AID mgr allocation failed"); 439 return QDF_STATUS_E_NOMEM; 440 } 441 442 for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) { 443 vdev_iter = ml_dev->wlan_vdev_list[i]; 444 if (!vdev_iter) 445 continue; 446 447 if (vdev != vdev_iter) 448 continue; 449 450 wlan_vdev_aid_mgr_free(ml_aidmgr->aid_mgr[i]); 451 ml_aidmgr->aid_mgr[i] = NULL; 452 break; 453 } 454 455 return QDF_STATUS_SUCCESS; 456 } 457 458 QDF_STATUS wlan_mlo_vdev_aid_mgr_init(struct wlan_mlo_dev_context *ml_dev) 459 { 460 uint8_t i; 461 uint8_t is_mbss_enabled = 0; 462 struct wlan_objmgr_vdev *vdev; 463 struct wlan_objmgr_vdev *tx_vdev = NULL; 464 struct wlan_vdev_aid_mgr *aid_mgr; 465 struct wlan_ml_vdev_aid_mgr *ml_aidmgr; 466 uint16_t max_aid = WLAN_UMAC_MAX_AID; 467 468 ml_aidmgr = qdf_mem_malloc(sizeof(struct wlan_ml_vdev_aid_mgr)); 469 if (!ml_aidmgr) { 470 ml_dev->ap_ctx->ml_aid_mgr = NULL; 471 mlo_err(" ML AID mgr allocation failed"); 472 return QDF_STATUS_E_NOMEM; 473 } 474 475 ml_aidmgr->max_aid = max_aid; 476 ml_dev->ap_ctx->ml_aid_mgr = ml_aidmgr; 477 478 for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) { 479 vdev = ml_dev->wlan_vdev_list[i]; 480 if (!vdev) 481 continue; 482 /* TODO */ 483 /* Get Tx VDEV, if VDEV is MBSSID */ 484 if (is_mbss_enabled) { 485 aid_mgr = wlan_vdev_mlme_get_aid_mgr(tx_vdev); 486 if (!aid_mgr) { 487 mlo_err("AID bitmap allocation failed for Tx VDEV%d", 488 wlan_vdev_get_id(tx_vdev)); 489 goto free_ml_aid_mgr; 490 } 491 492 qdf_atomic_inc(&aid_mgr->ref_cnt); 493 ml_aidmgr->aid_mgr[i] = aid_mgr; 494 } else { 495 ml_aidmgr->aid_mgr[i] = wlan_vdev_aid_mgr_init(max_aid); 496 if (!ml_aidmgr->aid_mgr[i]) { 497 mlo_err("AID bitmap allocation failed for VDEV%d", 498 wlan_vdev_get_id(vdev)); 499 goto free_ml_aid_mgr; 500 } 501 wlan_vdev_mlme_set_aid_mgr(vdev, 502 ml_aidmgr->aid_mgr[i]); 503 } 504 } 505 506 return QDF_STATUS_SUCCESS; 507 508 free_ml_aid_mgr: 509 wlan_mlo_vdev_aid_mgr_deinit(ml_dev); 510 511 return QDF_STATUS_E_NOMEM; 512 } 513 514 void wlan_mlo_vdev_aid_mgr_deinit(struct wlan_mlo_dev_context *ml_dev) 515 { 516 uint8_t i; 517 struct wlan_ml_vdev_aid_mgr *ml_aid_mgr; 518 int32_t n; 519 520 ml_aid_mgr = ml_dev->ap_ctx->ml_aid_mgr; 521 if (!ml_aid_mgr) 522 return; 523 524 for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) { 525 if (!ml_dev->wlan_vdev_list[i]) 526 continue; 527 528 if (ml_aid_mgr->aid_mgr[i]) { 529 n = qdf_atomic_read(&ml_aid_mgr->aid_mgr[i]->ref_cnt); 530 mlo_info("Vdev ID %d, AID mgr ref cnt %d", 531 wlan_vdev_get_id(ml_dev->wlan_vdev_list[i]), 532 n); 533 } else { 534 mlo_err("Vdev ID %d, doesn't have associated AID mgr", 535 wlan_vdev_get_id(ml_dev->wlan_vdev_list[i])); 536 continue; 537 } 538 wlan_vdev_aid_mgr_free(ml_aid_mgr->aid_mgr[i]); 539 ml_aid_mgr->aid_mgr[i] = NULL; 540 } 541 542 qdf_mem_free(ml_aid_mgr); 543 ml_dev->ap_ctx->ml_aid_mgr = NULL; 544 } 545