1 /* 2 * Copyright (c) 2023-2024 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 17 /* 18 * DOC: contains ML STA link force active/inactive related functionality 19 */ 20 #include "wlan_mlo_link_force.h" 21 #include "wlan_mlo_mgr_sta.h" 22 #include "wlan_policy_mgr_api.h" 23 #include "wlan_policy_mgr_i.h" 24 #include "wlan_cm_roam_public_struct.h" 25 #include "wlan_cm_roam_api.h" 26 #include "wlan_mlo_mgr_roam.h" 27 #include "wlan_mlme_main.h" 28 #include "wlan_mlo_mgr_link_switch.h" 29 #include "target_if.h" 30 31 void ml_nlink_convert_linkid_bitmap_to_vdev_bitmap(struct wlan_objmgr_psoc * psoc,struct wlan_objmgr_vdev * vdev,uint32_t link_bitmap,uint32_t * associated_bitmap,uint32_t * vdev_id_bitmap_sz,uint32_t vdev_id_bitmap[MLO_VDEV_BITMAP_SZ],uint8_t * vdev_id_num,uint8_t vdev_ids[WLAN_MLO_MAX_VDEVS])32 ml_nlink_convert_linkid_bitmap_to_vdev_bitmap( 33 struct wlan_objmgr_psoc *psoc, 34 struct wlan_objmgr_vdev *vdev, 35 uint32_t link_bitmap, 36 uint32_t *associated_bitmap, 37 uint32_t *vdev_id_bitmap_sz, 38 uint32_t vdev_id_bitmap[MLO_VDEV_BITMAP_SZ], 39 uint8_t *vdev_id_num, 40 uint8_t vdev_ids[WLAN_MLO_MAX_VDEVS]) 41 { 42 struct wlan_mlo_dev_context *mlo_dev_ctx; 43 struct wlan_mlo_sta *sta_ctx; 44 uint8_t i, j, bitmap_sz = 0, num_vdev = 0; 45 uint16_t link_id; 46 uint8_t vdev_id; 47 uint32_t associated_link_bitmap = 0; 48 uint8_t vdev_per_bitmap = MLO_MAX_VDEV_COUNT_PER_BIMTAP_ELEMENT; 49 50 *vdev_id_bitmap_sz = 0; 51 *vdev_id_num = 0; 52 qdf_mem_zero(vdev_id_bitmap, 53 sizeof(vdev_id_bitmap[0]) * MLO_VDEV_BITMAP_SZ); 54 qdf_mem_zero(vdev_ids, 55 sizeof(vdev_ids[0]) * WLAN_MLO_MAX_VDEVS); 56 if (associated_bitmap) 57 *associated_bitmap = 0; 58 59 mlo_dev_ctx = wlan_vdev_get_mlo_dev_ctx(vdev); 60 if (!mlo_dev_ctx || !mlo_dev_ctx->sta_ctx) { 61 mlo_err("mlo_ctx or sta_ctx null"); 62 return; 63 } 64 65 mlo_dev_lock_acquire(mlo_dev_ctx); 66 sta_ctx = mlo_dev_ctx->sta_ctx; 67 for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) { 68 /*todo: add standby link */ 69 if (!mlo_dev_ctx->wlan_vdev_list[i]) 70 continue; 71 vdev_id = wlan_vdev_get_id(mlo_dev_ctx->wlan_vdev_list[i]); 72 if (!qdf_test_bit(i, sta_ctx->wlan_connected_links)) { 73 mlo_debug("vdev %d is not connected", vdev_id); 74 continue; 75 } 76 77 link_id = wlan_vdev_get_link_id( 78 mlo_dev_ctx->wlan_vdev_list[i]); 79 if (link_id >= MAX_MLO_LINK_ID) { 80 mlo_err("invalid link id %d", link_id); 81 continue; 82 } 83 associated_link_bitmap |= 1 << link_id; 84 /* If the link_id is not interested one which is specified 85 * in "link_bitmap", continue the search. 86 */ 87 if (!(link_bitmap & (1 << link_id))) 88 continue; 89 j = vdev_id / vdev_per_bitmap; 90 if (j >= MLO_VDEV_BITMAP_SZ) 91 break; 92 vdev_id_bitmap[j] |= 1 << (vdev_id % vdev_per_bitmap); 93 if (j + 1 > bitmap_sz) 94 bitmap_sz = j + 1; 95 96 if (num_vdev >= WLAN_MLO_MAX_VDEVS) 97 break; 98 vdev_ids[num_vdev++] = vdev_id; 99 } 100 mlo_dev_lock_release(mlo_dev_ctx); 101 102 *vdev_id_bitmap_sz = bitmap_sz; 103 *vdev_id_num = num_vdev; 104 if (associated_bitmap) 105 *associated_bitmap = associated_link_bitmap; 106 107 mlo_debug("vdev %d link bitmap 0x%x vdev_bitmap 0x%x sz %d num %d assoc 0x%x for bitmap 0x%x", 108 wlan_vdev_get_id(vdev), link_bitmap & associated_link_bitmap, 109 vdev_id_bitmap[0], *vdev_id_bitmap_sz, num_vdev, 110 associated_link_bitmap, link_bitmap); 111 } 112 113 void ml_nlink_convert_vdev_bitmap_to_linkid_bitmap(struct wlan_objmgr_psoc * psoc,struct wlan_objmgr_vdev * vdev,uint32_t vdev_id_bitmap_sz,uint32_t * vdev_id_bitmap,uint32_t * link_bitmap,uint32_t * associated_bitmap)114 ml_nlink_convert_vdev_bitmap_to_linkid_bitmap( 115 struct wlan_objmgr_psoc *psoc, 116 struct wlan_objmgr_vdev *vdev, 117 uint32_t vdev_id_bitmap_sz, 118 uint32_t *vdev_id_bitmap, 119 uint32_t *link_bitmap, 120 uint32_t *associated_bitmap) 121 { 122 struct wlan_mlo_dev_context *mlo_dev_ctx; 123 struct wlan_mlo_sta *sta_ctx; 124 uint8_t i, j; 125 uint16_t link_id; 126 uint8_t vdev_id; 127 uint32_t associated_link_bitmap = 0; 128 uint8_t vdev_per_bitmap = MLO_MAX_VDEV_COUNT_PER_BIMTAP_ELEMENT; 129 130 *link_bitmap = 0; 131 if (associated_bitmap) 132 *associated_bitmap = 0; 133 if (!vdev_id_bitmap_sz) { 134 mlo_debug("vdev_id_bitmap_sz 0"); 135 return; 136 } 137 138 mlo_dev_ctx = wlan_vdev_get_mlo_dev_ctx(vdev); 139 if (!mlo_dev_ctx || !mlo_dev_ctx->sta_ctx) { 140 mlo_err("mlo_ctx or sta_ctx null"); 141 return; 142 } 143 144 sta_ctx = mlo_dev_ctx->sta_ctx; 145 mlo_dev_lock_acquire(mlo_dev_ctx); 146 for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) { 147 if (!mlo_dev_ctx->wlan_vdev_list[i]) 148 continue; 149 vdev_id = wlan_vdev_get_id(mlo_dev_ctx->wlan_vdev_list[i]); 150 if (!qdf_test_bit(i, sta_ctx->wlan_connected_links)) { 151 mlo_debug("vdev %d is not connected", vdev_id); 152 continue; 153 } 154 155 link_id = wlan_vdev_get_link_id( 156 mlo_dev_ctx->wlan_vdev_list[i]); 157 if (link_id >= MAX_MLO_LINK_ID) { 158 mlo_err("invalid link id %d", link_id); 159 continue; 160 } 161 associated_link_bitmap |= 1 << link_id; 162 j = vdev_id / vdev_per_bitmap; 163 if (j >= vdev_id_bitmap_sz) { 164 mlo_err("invalid vdev id %d", vdev_id); 165 continue; 166 } 167 /* If the vdev_id is not interested one which is specified 168 * in "vdev_id_bitmap", continue the search. 169 */ 170 if (!(vdev_id_bitmap[j] & (1 << (vdev_id % vdev_per_bitmap)))) 171 continue; 172 173 *link_bitmap |= 1 << link_id; 174 } 175 mlo_dev_lock_release(mlo_dev_ctx); 176 177 if (associated_bitmap) 178 *associated_bitmap = associated_link_bitmap; 179 mlo_debug("vdev %d link bitmap 0x%x vdev_bitmap 0x%x sz %d assoc 0x%x", 180 wlan_vdev_get_id(vdev), *link_bitmap, vdev_id_bitmap[0], 181 vdev_id_bitmap_sz, associated_link_bitmap); 182 } 183 184 void ml_nlink_get_curr_force_state(struct wlan_objmgr_psoc * psoc,struct wlan_objmgr_vdev * vdev,struct ml_link_force_state * force_cmd)185 ml_nlink_get_curr_force_state(struct wlan_objmgr_psoc *psoc, 186 struct wlan_objmgr_vdev *vdev, 187 struct ml_link_force_state *force_cmd) 188 { 189 struct wlan_mlo_dev_context *mlo_dev_ctx; 190 191 mlo_dev_ctx = wlan_vdev_get_mlo_dev_ctx(vdev); 192 if (!mlo_dev_ctx || !mlo_dev_ctx->sta_ctx) { 193 mlo_err("mlo_ctx or sta_ctx null"); 194 return; 195 } 196 197 mlo_dev_lock_acquire(mlo_dev_ctx); 198 qdf_mem_copy(force_cmd, 199 &mlo_dev_ctx->sta_ctx->link_force_ctx.force_state, 200 sizeof(*force_cmd)); 201 mlo_dev_lock_release(mlo_dev_ctx); 202 } 203 204 void ml_nlink_clr_force_state(struct wlan_objmgr_psoc * psoc,struct wlan_objmgr_vdev * vdev)205 ml_nlink_clr_force_state(struct wlan_objmgr_psoc *psoc, 206 struct wlan_objmgr_vdev *vdev) 207 { 208 struct wlan_mlo_dev_context *mlo_dev_ctx; 209 struct ml_link_force_state *force_state; 210 211 mlo_dev_ctx = wlan_vdev_get_mlo_dev_ctx(vdev); 212 if (!mlo_dev_ctx || !mlo_dev_ctx->sta_ctx) 213 return; 214 215 mlo_dev_lock_acquire(mlo_dev_ctx); 216 force_state = &mlo_dev_ctx->sta_ctx->link_force_ctx.force_state; 217 qdf_mem_zero(force_state, sizeof(*force_state)); 218 ml_nlink_dump_force_state(force_state, ""); 219 qdf_mem_zero(mlo_dev_ctx->sta_ctx->link_force_ctx.reqs, 220 sizeof(mlo_dev_ctx->sta_ctx->link_force_ctx.reqs)); 221 mlo_dev_lock_release(mlo_dev_ctx); 222 } 223 224 static void ml_nlink_update_link_bitmap(uint16_t * curr_link_bitmap,uint16_t link_bitmap,enum set_curr_control ctrl)225 ml_nlink_update_link_bitmap(uint16_t *curr_link_bitmap, 226 uint16_t link_bitmap, 227 enum set_curr_control ctrl) 228 { 229 switch (ctrl) { 230 case LINK_OVERWRITE: 231 *curr_link_bitmap = link_bitmap; 232 break; 233 case LINK_CLR: 234 *curr_link_bitmap &= ~link_bitmap; 235 break; 236 case LINK_ADD: 237 *curr_link_bitmap |= link_bitmap; 238 break; 239 default: 240 mlo_err("unknown update ctrl %d", ctrl); 241 return; 242 } 243 } 244 245 void ml_nlink_set_curr_force_active_state(struct wlan_objmgr_psoc * psoc,struct wlan_objmgr_vdev * vdev,uint16_t link_bitmap,enum set_curr_control ctrl)246 ml_nlink_set_curr_force_active_state(struct wlan_objmgr_psoc *psoc, 247 struct wlan_objmgr_vdev *vdev, 248 uint16_t link_bitmap, 249 enum set_curr_control ctrl) 250 { 251 struct wlan_mlo_dev_context *mlo_dev_ctx; 252 struct ml_link_force_state *force_state; 253 254 mlo_dev_ctx = wlan_vdev_get_mlo_dev_ctx(vdev); 255 if (!mlo_dev_ctx || !mlo_dev_ctx->sta_ctx) { 256 mlo_err("mlo_ctx or sta_ctx null"); 257 return; 258 } 259 260 mlo_dev_lock_acquire(mlo_dev_ctx); 261 force_state = &mlo_dev_ctx->sta_ctx->link_force_ctx.force_state; 262 ml_nlink_update_link_bitmap(&force_state->force_active_bitmap, 263 link_bitmap, ctrl); 264 ml_nlink_dump_force_state(force_state, ":ctrl %d bitmap 0x%x", 265 ctrl, link_bitmap); 266 mlo_dev_lock_release(mlo_dev_ctx); 267 } 268 269 void ml_nlink_set_curr_force_inactive_state(struct wlan_objmgr_psoc * psoc,struct wlan_objmgr_vdev * vdev,uint16_t link_bitmap,enum set_curr_control ctrl)270 ml_nlink_set_curr_force_inactive_state(struct wlan_objmgr_psoc *psoc, 271 struct wlan_objmgr_vdev *vdev, 272 uint16_t link_bitmap, 273 enum set_curr_control ctrl) 274 { 275 struct wlan_mlo_dev_context *mlo_dev_ctx; 276 struct ml_link_force_state *force_state; 277 278 mlo_dev_ctx = wlan_vdev_get_mlo_dev_ctx(vdev); 279 if (!mlo_dev_ctx || !mlo_dev_ctx->sta_ctx) { 280 mlo_err("mlo_ctx or sta_ctx null"); 281 return; 282 } 283 284 mlo_dev_lock_acquire(mlo_dev_ctx); 285 force_state = &mlo_dev_ctx->sta_ctx->link_force_ctx.force_state; 286 ml_nlink_update_link_bitmap(&force_state->force_inactive_bitmap, 287 link_bitmap, ctrl); 288 ml_nlink_dump_force_state(force_state, ":ctrl %d bitmap 0x%x", ctrl, 289 link_bitmap); 290 mlo_dev_lock_release(mlo_dev_ctx); 291 } 292 293 void ml_nlink_set_curr_force_active_num_state(struct wlan_objmgr_psoc * psoc,struct wlan_objmgr_vdev * vdev,uint8_t link_num,uint16_t link_bitmap)294 ml_nlink_set_curr_force_active_num_state(struct wlan_objmgr_psoc *psoc, 295 struct wlan_objmgr_vdev *vdev, 296 uint8_t link_num, 297 uint16_t link_bitmap) 298 { 299 struct wlan_mlo_dev_context *mlo_dev_ctx; 300 struct ml_link_force_state *force_state; 301 302 mlo_dev_ctx = wlan_vdev_get_mlo_dev_ctx(vdev); 303 if (!mlo_dev_ctx || !mlo_dev_ctx->sta_ctx) { 304 mlo_err("mlo_ctx or sta_ctx null"); 305 return; 306 } 307 308 mlo_dev_lock_acquire(mlo_dev_ctx); 309 force_state = &mlo_dev_ctx->sta_ctx->link_force_ctx.force_state; 310 force_state->force_active_num = link_num; 311 force_state->force_active_num_bitmap = link_bitmap; 312 ml_nlink_dump_force_state(force_state, ":num %d bitmap 0x%x", 313 link_num, link_bitmap); 314 mlo_dev_lock_release(mlo_dev_ctx); 315 } 316 317 void ml_nlink_set_curr_force_inactive_num_state(struct wlan_objmgr_psoc * psoc,struct wlan_objmgr_vdev * vdev,uint8_t link_num,uint16_t link_bitmap)318 ml_nlink_set_curr_force_inactive_num_state(struct wlan_objmgr_psoc *psoc, 319 struct wlan_objmgr_vdev *vdev, 320 uint8_t link_num, 321 uint16_t link_bitmap) 322 { 323 struct wlan_mlo_dev_context *mlo_dev_ctx; 324 struct ml_link_force_state *force_state; 325 326 mlo_dev_ctx = wlan_vdev_get_mlo_dev_ctx(vdev); 327 if (!mlo_dev_ctx || !mlo_dev_ctx->sta_ctx) { 328 mlo_err("mlo_ctx or sta_ctx null"); 329 return; 330 } 331 332 mlo_dev_lock_acquire(mlo_dev_ctx); 333 force_state = &mlo_dev_ctx->sta_ctx->link_force_ctx.force_state; 334 force_state->force_inactive_num = link_num; 335 force_state->force_inactive_num_bitmap = link_bitmap; 336 ml_nlink_dump_force_state(force_state, ":num %d bitmap 0x%x", 337 link_num, link_bitmap); 338 mlo_dev_lock_release(mlo_dev_ctx); 339 } 340 341 void ml_nlink_set_dynamic_inactive_links(struct wlan_objmgr_psoc * psoc,struct wlan_objmgr_vdev * vdev,uint16_t dynamic_link_bitmap)342 ml_nlink_set_dynamic_inactive_links(struct wlan_objmgr_psoc *psoc, 343 struct wlan_objmgr_vdev *vdev, 344 uint16_t dynamic_link_bitmap) 345 { 346 struct wlan_mlo_dev_context *mlo_dev_ctx; 347 struct ml_link_force_state *force_state; 348 349 mlo_dev_ctx = wlan_vdev_get_mlo_dev_ctx(vdev); 350 if (!mlo_dev_ctx || !mlo_dev_ctx->sta_ctx) { 351 mlo_err("mlo_ctx or sta_ctx null"); 352 return; 353 } 354 355 mlo_dev_lock_acquire(mlo_dev_ctx); 356 force_state = &mlo_dev_ctx->sta_ctx->link_force_ctx.force_state; 357 force_state->curr_dynamic_inactive_bitmap = dynamic_link_bitmap; 358 ml_nlink_dump_force_state(force_state, ":dynamic bitmap 0x%x", 359 dynamic_link_bitmap); 360 mlo_dev_lock_release(mlo_dev_ctx); 361 } 362 363 static void ml_nlink_update_force_link_request(struct wlan_objmgr_psoc * psoc,struct wlan_objmgr_vdev * vdev,struct set_link_req * req,enum set_link_source source)364 ml_nlink_update_force_link_request(struct wlan_objmgr_psoc *psoc, 365 struct wlan_objmgr_vdev *vdev, 366 struct set_link_req *req, 367 enum set_link_source source) 368 { 369 struct wlan_mlo_dev_context *mlo_dev_ctx; 370 struct set_link_req *old; 371 372 mlo_dev_ctx = wlan_vdev_get_mlo_dev_ctx(vdev); 373 if (!mlo_dev_ctx || !mlo_dev_ctx->sta_ctx) { 374 mlo_err("mlo_ctx or sta_ctx null"); 375 return; 376 } 377 if (source >= SET_LINK_SOURCE_MAX || source < 0) { 378 mlo_err("invalid source %d", source); 379 return; 380 } 381 mlo_dev_lock_acquire(mlo_dev_ctx); 382 old = &mlo_dev_ctx->sta_ctx->link_force_ctx.reqs[source]; 383 *old = *req; 384 mlo_dev_lock_release(mlo_dev_ctx); 385 } 386 387 static void ml_nlink_update_concurrency_link_request(struct wlan_objmgr_psoc * psoc,struct wlan_objmgr_vdev * vdev,struct ml_link_force_state * force_state,enum mlo_link_force_reason reason)388 ml_nlink_update_concurrency_link_request( 389 struct wlan_objmgr_psoc *psoc, 390 struct wlan_objmgr_vdev *vdev, 391 struct ml_link_force_state *force_state, 392 enum mlo_link_force_reason reason) 393 { 394 struct wlan_mlo_dev_context *mlo_dev_ctx; 395 struct set_link_req *req; 396 397 mlo_dev_ctx = wlan_vdev_get_mlo_dev_ctx(vdev); 398 if (!mlo_dev_ctx || !mlo_dev_ctx->sta_ctx) { 399 mlo_err("mlo_ctx or sta_ctx null"); 400 return; 401 } 402 mlo_dev_lock_acquire(mlo_dev_ctx); 403 req = 404 &mlo_dev_ctx->sta_ctx->link_force_ctx.reqs[SET_LINK_FROM_CONCURRENCY]; 405 req->reason = reason; 406 req->force_active_bitmap = force_state->force_active_bitmap; 407 req->force_inactive_bitmap = force_state->force_inactive_bitmap; 408 req->force_active_num = force_state->force_active_num; 409 req->force_inactive_num = force_state->force_inactive_num; 410 req->force_inactive_num_bitmap = 411 force_state->force_inactive_num_bitmap; 412 mlo_dev_lock_release(mlo_dev_ctx); 413 } 414 ml_nlink_init_concurrency_link_request(struct wlan_objmgr_psoc * psoc,struct wlan_objmgr_vdev * vdev)415 void ml_nlink_init_concurrency_link_request( 416 struct wlan_objmgr_psoc *psoc, 417 struct wlan_objmgr_vdev *vdev) 418 { 419 struct wlan_mlo_dev_context *mlo_dev_ctx; 420 struct set_link_req *req; 421 struct ml_link_force_state *force_state; 422 423 mlo_dev_ctx = wlan_vdev_get_mlo_dev_ctx(vdev); 424 if (!mlo_dev_ctx || !mlo_dev_ctx->sta_ctx) { 425 mlo_err("mlo_ctx or sta_ctx null"); 426 return; 427 } 428 mlo_dev_lock_acquire(mlo_dev_ctx); 429 force_state = &mlo_dev_ctx->sta_ctx->link_force_ctx.force_state; 430 req = 431 &mlo_dev_ctx->sta_ctx->link_force_ctx.reqs[SET_LINK_FROM_CONCURRENCY]; 432 req->reason = MLO_LINK_FORCE_REASON_CONNECT; 433 req->force_active_bitmap = force_state->force_active_bitmap; 434 req->force_inactive_bitmap = force_state->force_inactive_bitmap; 435 req->force_active_num = force_state->force_active_num; 436 req->force_inactive_num = force_state->force_inactive_num; 437 req->force_inactive_num_bitmap = 438 force_state->force_inactive_num_bitmap; 439 mlo_dev_lock_release(mlo_dev_ctx); 440 } 441 442 void ml_nlink_get_force_link_request(struct wlan_objmgr_psoc * psoc,struct wlan_objmgr_vdev * vdev,struct set_link_req * req,enum set_link_source source)443 ml_nlink_get_force_link_request(struct wlan_objmgr_psoc *psoc, 444 struct wlan_objmgr_vdev *vdev, 445 struct set_link_req *req, 446 enum set_link_source source) 447 { 448 struct wlan_mlo_dev_context *mlo_dev_ctx; 449 struct set_link_req *old; 450 451 mlo_dev_ctx = wlan_vdev_get_mlo_dev_ctx(vdev); 452 if (!mlo_dev_ctx || !mlo_dev_ctx->sta_ctx) { 453 mlo_err("mlo_ctx or sta_ctx null"); 454 return; 455 } 456 if (source >= SET_LINK_SOURCE_MAX || source < 0) { 457 mlo_err("invalid source %d", source); 458 return; 459 } 460 mlo_dev_lock_acquire(mlo_dev_ctx); 461 old = &mlo_dev_ctx->sta_ctx->link_force_ctx.reqs[source]; 462 *req = *old; 463 mlo_dev_lock_release(mlo_dev_ctx); 464 } 465 466 static void ml_nlink_clr_force_link_request(struct wlan_objmgr_psoc * psoc,struct wlan_objmgr_vdev * vdev,enum set_link_source source)467 ml_nlink_clr_force_link_request(struct wlan_objmgr_psoc *psoc, 468 struct wlan_objmgr_vdev *vdev, 469 enum set_link_source source) 470 { 471 struct wlan_mlo_dev_context *mlo_dev_ctx; 472 struct set_link_req *req; 473 474 mlo_dev_ctx = wlan_vdev_get_mlo_dev_ctx(vdev); 475 if (!mlo_dev_ctx || !mlo_dev_ctx->sta_ctx) { 476 mlo_err("mlo_ctx or sta_ctx null"); 477 return; 478 } 479 if (source >= SET_LINK_SOURCE_MAX || source < 0) { 480 mlo_err("invalid source %d", source); 481 return; 482 } 483 484 mlo_dev_lock_acquire(mlo_dev_ctx); 485 req = &mlo_dev_ctx->sta_ctx->link_force_ctx.reqs[source]; 486 qdf_mem_zero(req, sizeof(*req)); 487 mlo_dev_lock_release(mlo_dev_ctx); 488 } 489 490 void ml_nlink_get_dynamic_inactive_links(struct wlan_objmgr_psoc * psoc,struct wlan_objmgr_vdev * vdev,uint16_t * dynamic_link_bitmap,uint16_t * force_link_bitmap)491 ml_nlink_get_dynamic_inactive_links(struct wlan_objmgr_psoc *psoc, 492 struct wlan_objmgr_vdev *vdev, 493 uint16_t *dynamic_link_bitmap, 494 uint16_t *force_link_bitmap) 495 { 496 struct wlan_mlo_dev_context *mlo_dev_ctx; 497 struct ml_link_force_state *force_state; 498 499 mlo_dev_ctx = wlan_vdev_get_mlo_dev_ctx(vdev); 500 if (!mlo_dev_ctx || !mlo_dev_ctx->sta_ctx) { 501 mlo_err("mlo_ctx or sta_ctx null"); 502 return; 503 } 504 505 mlo_dev_lock_acquire(mlo_dev_ctx); 506 force_state = &mlo_dev_ctx->sta_ctx->link_force_ctx.force_state; 507 *dynamic_link_bitmap = force_state->curr_dynamic_inactive_bitmap; 508 *force_link_bitmap = force_state->force_inactive_bitmap; 509 mlo_dev_lock_release(mlo_dev_ctx); 510 } 511 512 /** 513 * ml_nlink_get_affect_ml_sta() - Get ML STA whose link can be 514 * force inactive 515 * @psoc: PSOC object information 516 * 517 * At present we only support one ML STA. so ml_nlink_get_affect_ml_sta 518 * is invoked to get one ML STA vdev from policy mgr table. 519 * In future if ML STA+ML STA supported, we may need to extend it 520 * to find one ML STA which is required to force inactve/active. 521 * 522 * Return: vdev object 523 */ 524 static struct wlan_objmgr_vdev * ml_nlink_get_affect_ml_sta(struct wlan_objmgr_psoc * psoc)525 ml_nlink_get_affect_ml_sta(struct wlan_objmgr_psoc *psoc) 526 { 527 uint8_t num_ml_sta = 0, num_disabled_ml_sta = 0; 528 uint8_t ml_sta_vdev_lst[MAX_NUMBER_OF_CONC_CONNECTIONS] = {0}; 529 qdf_freq_t ml_freq_lst[MAX_NUMBER_OF_CONC_CONNECTIONS] = {0}; 530 struct wlan_objmgr_vdev *vdev; 531 532 policy_mgr_get_ml_sta_info_psoc(psoc, &num_ml_sta, 533 &num_disabled_ml_sta, 534 ml_sta_vdev_lst, ml_freq_lst, NULL, 535 NULL, NULL); 536 if (!num_ml_sta || num_ml_sta > MAX_NUMBER_OF_CONC_CONNECTIONS) 537 return NULL; 538 539 if (num_ml_sta > MAX_NUMBER_OF_CONC_CONNECTIONS) { 540 mlo_debug("unexpected num_ml_sta %d", num_ml_sta); 541 return NULL; 542 } 543 vdev = wlan_objmgr_get_vdev_by_id_from_psoc( 544 psoc, ml_sta_vdev_lst[0], 545 WLAN_MLO_MGR_ID); 546 if (!vdev) { 547 mlo_err("invalid vdev for id %d", ml_sta_vdev_lst[0]); 548 return NULL; 549 } 550 551 return vdev; 552 } 553 ml_is_nlink_service_supported(struct wlan_objmgr_psoc * psoc)554 bool ml_is_nlink_service_supported(struct wlan_objmgr_psoc *psoc) 555 { 556 struct wmi_unified *wmi_handle; 557 558 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 559 if (!wmi_handle) { 560 mlo_err("Invalid WMI handle"); 561 return false; 562 } 563 return wmi_service_enabled( 564 wmi_handle, 565 wmi_service_n_link_mlo_support); 566 } 567 568 /* Exclude AP removed link */ 569 #define NLINK_EXCLUDE_REMOVED_LINK 0x01 570 /* Include AP removed link only, can't work with other flags */ 571 #define NLINK_INCLUDE_REMOVED_LINK_ONLY 0x02 572 /* Exclude QUITE link */ 573 #define NLINK_EXCLUDE_QUIET_LINK 0x04 574 /* Exclude standby link information */ 575 #define NLINK_EXCLUDE_STANDBY_LINK 0x08 576 /* Dump link information */ 577 #define NLINK_DUMP_LINK 0x10 578 579 static void ml_nlink_get_standby_link_info(struct wlan_objmgr_psoc * psoc,struct wlan_objmgr_vdev * vdev,uint8_t flag,uint8_t ml_num_link_sz,struct ml_link_info * ml_link_info,qdf_freq_t * ml_freq_lst,uint8_t * ml_vdev_lst,uint8_t * ml_linkid_lst,uint8_t * ml_num_link,uint32_t * ml_link_bitmap)580 ml_nlink_get_standby_link_info(struct wlan_objmgr_psoc *psoc, 581 struct wlan_objmgr_vdev *vdev, 582 uint8_t flag, 583 uint8_t ml_num_link_sz, 584 struct ml_link_info *ml_link_info, 585 qdf_freq_t *ml_freq_lst, 586 uint8_t *ml_vdev_lst, 587 uint8_t *ml_linkid_lst, 588 uint8_t *ml_num_link, 589 uint32_t *ml_link_bitmap) 590 { 591 struct mlo_link_info *link_info; 592 uint8_t link_info_iter; 593 594 link_info = mlo_mgr_get_ap_link(vdev); 595 if (!link_info) 596 return; 597 598 for (link_info_iter = 0; link_info_iter < WLAN_MAX_ML_BSS_LINKS; 599 link_info_iter++) { 600 if (qdf_is_macaddr_zero(&link_info->ap_link_addr)) 601 break; 602 603 if (link_info->vdev_id == WLAN_INVALID_VDEV_ID) { 604 if (*ml_num_link >= ml_num_link_sz) { 605 mlo_debug("link lst overflow"); 606 break; 607 } 608 if (!link_info->link_chan_info->ch_freq) { 609 mlo_debug("link freq 0!"); 610 break; 611 } 612 if (*ml_link_bitmap & (1 << link_info->link_id)) { 613 mlo_debug("unexpected standby linkid %d", 614 link_info->link_id); 615 break; 616 } 617 if (link_info->link_id >= MAX_MLO_LINK_ID) { 618 mlo_debug("invalid standby link id %d", 619 link_info->link_id); 620 break; 621 } 622 623 if ((flag & NLINK_EXCLUDE_REMOVED_LINK) && 624 qdf_atomic_test_bit( 625 LS_F_AP_REMOVAL_BIT, 626 &link_info->link_status_flags)) { 627 mlo_debug("standby link %d is removed", 628 link_info->link_id); 629 continue; 630 } 631 if ((flag & NLINK_INCLUDE_REMOVED_LINK_ONLY) && 632 !qdf_atomic_test_bit( 633 LS_F_AP_REMOVAL_BIT, 634 &link_info->link_status_flags)) { 635 continue; 636 } 637 638 ml_freq_lst[*ml_num_link] = 639 link_info->link_chan_info->ch_freq; 640 ml_vdev_lst[*ml_num_link] = WLAN_INVALID_VDEV_ID; 641 ml_linkid_lst[*ml_num_link] = link_info->link_id; 642 *ml_link_bitmap |= 1 << link_info->link_id; 643 if (flag & NLINK_DUMP_LINK) 644 mlo_debug("vdev %d link %d freq %d bitmap 0x%x flag 0x%x", 645 ml_vdev_lst[*ml_num_link], 646 ml_linkid_lst[*ml_num_link], 647 ml_freq_lst[*ml_num_link], 648 *ml_link_bitmap, flag); 649 (*ml_num_link)++; 650 } 651 652 link_info++; 653 } 654 } 655 656 uint32_t ml_nlink_get_standby_link_bitmap(struct wlan_objmgr_psoc * psoc,struct wlan_objmgr_vdev * vdev)657 ml_nlink_get_standby_link_bitmap(struct wlan_objmgr_psoc *psoc, 658 struct wlan_objmgr_vdev *vdev) 659 { 660 uint8_t ml_num_link = 0; 661 uint32_t standby_link_bitmap = 0; 662 uint8_t ml_vdev_lst[MAX_NUMBER_OF_CONC_CONNECTIONS]; 663 qdf_freq_t ml_freq_lst[MAX_NUMBER_OF_CONC_CONNECTIONS]; 664 uint8_t ml_linkid_lst[MAX_NUMBER_OF_CONC_CONNECTIONS]; 665 struct ml_link_info ml_link_info[MAX_NUMBER_OF_CONC_CONNECTIONS]; 666 667 ml_nlink_get_standby_link_info(psoc, vdev, NLINK_DUMP_LINK, 668 QDF_ARRAY_SIZE(ml_linkid_lst), 669 ml_link_info, ml_freq_lst, ml_vdev_lst, 670 ml_linkid_lst, &ml_num_link, 671 &standby_link_bitmap); 672 673 return standby_link_bitmap; 674 } 675 676 /** 677 * ml_nlink_get_link_info() - Get ML STA link info 678 * @psoc: PSOC object information 679 * @vdev: ml sta vdev object 680 * @flag: flag NLINK_* to specify what links should be returned 681 * @ml_num_link_sz: input array size of ml_link_info and 682 * other parameters. 683 * @ml_link_info: ml link info array 684 * @ml_freq_lst: channel frequency list 685 * @ml_vdev_lst: vdev id list 686 * @ml_linkid_lst: link id list 687 * @ml_num_link: num of links 688 * @ml_link_bitmap: link bitmaps. 689 * 690 * Return: void 691 */ ml_nlink_get_link_info(struct wlan_objmgr_psoc * psoc,struct wlan_objmgr_vdev * vdev,uint8_t flag,uint8_t ml_num_link_sz,struct ml_link_info * ml_link_info,qdf_freq_t * ml_freq_lst,uint8_t * ml_vdev_lst,uint8_t * ml_linkid_lst,uint8_t * ml_num_link,uint32_t * ml_link_bitmap)692 static void ml_nlink_get_link_info(struct wlan_objmgr_psoc *psoc, 693 struct wlan_objmgr_vdev *vdev, 694 uint8_t flag, 695 uint8_t ml_num_link_sz, 696 struct ml_link_info *ml_link_info, 697 qdf_freq_t *ml_freq_lst, 698 uint8_t *ml_vdev_lst, 699 uint8_t *ml_linkid_lst, 700 uint8_t *ml_num_link, 701 uint32_t *ml_link_bitmap) 702 { 703 struct wlan_mlo_dev_context *mlo_dev_ctx; 704 struct wlan_mlo_sta *sta_ctx; 705 uint8_t i, num_link = 0; 706 uint32_t link_bitmap = 0; 707 uint16_t link_id; 708 uint8_t vdev_id; 709 bool connected = false; 710 711 *ml_num_link = 0; 712 *ml_link_bitmap = 0; 713 qdf_mem_zero(ml_link_info, sizeof(*ml_link_info) * ml_num_link_sz); 714 qdf_mem_zero(ml_freq_lst, sizeof(*ml_freq_lst) * ml_num_link_sz); 715 qdf_mem_zero(ml_linkid_lst, sizeof(*ml_linkid_lst) * ml_num_link_sz); 716 qdf_mem_zero(ml_vdev_lst, sizeof(*ml_vdev_lst) * ml_num_link_sz); 717 718 mlo_dev_ctx = wlan_vdev_get_mlo_dev_ctx(vdev); 719 if (!mlo_dev_ctx || !mlo_dev_ctx->sta_ctx) { 720 mlo_err("mlo_ctx or sta_ctx null"); 721 return; 722 } 723 724 mlo_dev_lock_acquire(mlo_dev_ctx); 725 sta_ctx = mlo_dev_ctx->sta_ctx; 726 727 link_bitmap = 0; 728 for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) { 729 if (!mlo_dev_ctx->wlan_vdev_list[i]) 730 continue; 731 if (!qdf_test_bit(i, sta_ctx->wlan_connected_links)) 732 continue; 733 734 if (!wlan_cm_is_vdev_connected( 735 mlo_dev_ctx->wlan_vdev_list[i])) { 736 mlo_debug("Vdev id %d is not in connected state", 737 wlan_vdev_get_id( 738 mlo_dev_ctx->wlan_vdev_list[i])); 739 continue; 740 } 741 connected = true; 742 743 vdev_id = wlan_vdev_get_id(mlo_dev_ctx->wlan_vdev_list[i]); 744 link_id = wlan_vdev_get_link_id( 745 mlo_dev_ctx->wlan_vdev_list[i]); 746 if (link_id >= MAX_MLO_LINK_ID) { 747 mlo_debug("invalid link id %x for vdev %d", 748 link_id, vdev_id); 749 continue; 750 } 751 752 if ((flag & NLINK_EXCLUDE_REMOVED_LINK) && 753 wlan_get_vdev_link_removed_flag_by_vdev_id( 754 psoc, vdev_id)) { 755 mlo_debug("vdev id %d link %d is removed", 756 vdev_id, link_id); 757 continue; 758 } 759 if ((flag & NLINK_INCLUDE_REMOVED_LINK_ONLY) && 760 !wlan_get_vdev_link_removed_flag_by_vdev_id( 761 psoc, vdev_id)) { 762 continue; 763 } 764 if ((flag & NLINK_EXCLUDE_QUIET_LINK) && 765 mlo_is_sta_in_quiet_status(mlo_dev_ctx, link_id)) { 766 mlo_debug("vdev id %d link %d is quiet", 767 vdev_id, link_id); 768 continue; 769 } 770 771 if (num_link >= ml_num_link_sz) 772 break; 773 ml_freq_lst[num_link] = wlan_get_operation_chan_freq( 774 mlo_dev_ctx->wlan_vdev_list[i]); 775 ml_vdev_lst[num_link] = vdev_id; 776 ml_linkid_lst[num_link] = link_id; 777 link_bitmap |= 1 << link_id; 778 if (flag & NLINK_DUMP_LINK) 779 mlo_debug("vdev %d link %d freq %d bitmap 0x%x flag 0x%x", 780 ml_vdev_lst[num_link], 781 ml_linkid_lst[num_link], 782 ml_freq_lst[num_link], link_bitmap, flag); 783 num_link++; 784 } 785 /* Add standby link only if mlo sta is connected */ 786 if (connected && !(flag & NLINK_EXCLUDE_STANDBY_LINK)) 787 ml_nlink_get_standby_link_info(psoc, vdev, flag, 788 ml_num_link_sz, 789 ml_link_info, 790 ml_freq_lst, 791 ml_vdev_lst, 792 ml_linkid_lst, 793 &num_link, 794 &link_bitmap); 795 796 mlo_dev_lock_release(mlo_dev_ctx); 797 *ml_num_link = num_link; 798 *ml_link_bitmap = link_bitmap; 799 } 800 801 uint32_t convert_link_bitmap_to_link_ids(uint32_t link_bitmap,uint8_t link_id_sz,uint8_t * link_ids)802 convert_link_bitmap_to_link_ids(uint32_t link_bitmap, 803 uint8_t link_id_sz, 804 uint8_t *link_ids) 805 { 806 uint32_t i = 0; 807 uint8_t id = 0; 808 809 while (link_bitmap) { 810 if (link_bitmap & 1) { 811 if (id >= 15) { 812 /* warning */ 813 mlo_err("linkid invalid %d 0x%x", 814 id, link_bitmap); 815 break; 816 } 817 if (link_ids) { 818 if (i >= link_id_sz) { 819 /* warning */ 820 mlo_err("linkid buff overflow 0x%x", 821 link_bitmap); 822 break; 823 } 824 link_ids[i] = id; 825 } 826 i++; 827 } 828 link_bitmap >>= 1; 829 id++; 830 } 831 832 return i; 833 } 834 835 uint32_t ml_nlink_convert_link_bitmap_to_ids(uint32_t link_bitmap,uint8_t link_id_sz,uint8_t * link_ids)836 ml_nlink_convert_link_bitmap_to_ids(uint32_t link_bitmap, 837 uint8_t link_id_sz, 838 uint8_t *link_ids) 839 { 840 return convert_link_bitmap_to_link_ids(link_bitmap, link_id_sz, 841 link_ids); 842 } 843 844 /** 845 * ml_nlink_handle_mcc_links() - Check force inactive needed 846 * if ML STA links are in MCC channels 847 * @psoc: PSOC object information 848 * @vdev: vdev object 849 * @force_cmd: force command to be returned 850 * 851 * This API will return force inactive number 1 in force_cmd 852 * if STA links are in MCC channels with the link bitmap including 853 * the MCC links id. 854 * If the link is marked removed by AP MLD, return force inactive 855 * bitmap with removed link id bitmap as well. 856 * 857 * Return: void 858 */ 859 static void ml_nlink_handle_mcc_links(struct wlan_objmgr_psoc * psoc,struct wlan_objmgr_vdev * vdev,struct ml_link_force_state * force_cmd)860 ml_nlink_handle_mcc_links(struct wlan_objmgr_psoc *psoc, 861 struct wlan_objmgr_vdev *vdev, 862 struct ml_link_force_state *force_cmd) 863 { 864 uint8_t ml_num_link = 0; 865 uint32_t ml_link_bitmap = 0, affected_link_bitmap = 0; 866 uint32_t force_inactive_link_bitmap = 0; 867 uint8_t ml_vdev_lst[MAX_NUMBER_OF_CONC_CONNECTIONS]; 868 qdf_freq_t ml_freq_lst[MAX_NUMBER_OF_CONC_CONNECTIONS]; 869 uint8_t ml_linkid_lst[MAX_NUMBER_OF_CONC_CONNECTIONS]; 870 struct ml_link_info ml_link_info[MAX_NUMBER_OF_CONC_CONNECTIONS]; 871 872 ml_nlink_get_link_info(psoc, vdev, NLINK_INCLUDE_REMOVED_LINK_ONLY | 873 NLINK_DUMP_LINK, 874 QDF_ARRAY_SIZE(ml_linkid_lst), 875 ml_link_info, ml_freq_lst, ml_vdev_lst, 876 ml_linkid_lst, &ml_num_link, 877 &force_inactive_link_bitmap); 878 if (force_inactive_link_bitmap) { 879 /* AP removed link will be force inactive always */ 880 force_cmd->force_inactive_bitmap = force_inactive_link_bitmap; 881 mlo_debug("AP removed link 0x%x", force_inactive_link_bitmap); 882 } 883 884 ml_nlink_get_link_info(psoc, vdev, NLINK_EXCLUDE_REMOVED_LINK | 885 NLINK_DUMP_LINK, 886 QDF_ARRAY_SIZE(ml_linkid_lst), 887 ml_link_info, ml_freq_lst, ml_vdev_lst, 888 ml_linkid_lst, &ml_num_link, 889 &ml_link_bitmap); 890 if (ml_num_link < 2) 891 return; 892 893 policy_mgr_is_ml_sta_links_in_mcc(psoc, ml_freq_lst, 894 ml_vdev_lst, 895 ml_linkid_lst, 896 ml_num_link, 897 &affected_link_bitmap); 898 if (affected_link_bitmap) { 899 force_cmd->force_inactive_num = 900 convert_link_bitmap_to_link_ids( 901 affected_link_bitmap, 0, NULL); 902 if (force_cmd->force_inactive_num > 1) { 903 force_cmd->force_inactive_num--; 904 force_cmd->force_inactive_num_bitmap = 905 affected_link_bitmap; 906 } else { 907 force_cmd->force_inactive_num = 0; 908 } 909 } 910 if (force_inactive_link_bitmap || affected_link_bitmap) 911 ml_nlink_dump_force_state(force_cmd, ""); 912 } 913 914 /** 915 * ml_nlink_handle_legacy_sta_intf() - Check force inactive needed 916 * with legacy STA 917 * @psoc: PSOC object information 918 * @vdev: vdev object 919 * @force_cmd: force command to be returned 920 * @sta_vdev_id: legacy STA vdev id 921 * @non_ml_sta_freq: legacy STA channel frequency 922 * 923 * If legacy STA is MCC with any link of MLO STA, the mlo link 924 * will be forced inactive. And if 3 link MLO case, the left 925 * 2 links have to be force inactive with num 1. For example, 926 * ML STA 2+5+6, legacy STA on MCC channel of 5G link, then 927 * 5G will be force inactive, and left 2+6 link will be force 928 * inactive by inactive link num = 1 (with link bitmap 2+6). 929 * 930 * Return: void 931 */ 932 static void ml_nlink_handle_legacy_sta_intf(struct wlan_objmgr_psoc * psoc,struct wlan_objmgr_vdev * vdev,struct ml_link_force_state * force_cmd,uint8_t sta_vdev_id,qdf_freq_t non_ml_sta_freq)933 ml_nlink_handle_legacy_sta_intf(struct wlan_objmgr_psoc *psoc, 934 struct wlan_objmgr_vdev *vdev, 935 struct ml_link_force_state *force_cmd, 936 uint8_t sta_vdev_id, 937 qdf_freq_t non_ml_sta_freq) 938 { 939 uint8_t ml_num_link = 0; 940 uint32_t ml_link_bitmap = 0, affected_link_bitmap = 0; 941 uint32_t force_inactive_link_bitmap = 0; 942 uint8_t ml_vdev_lst[MAX_NUMBER_OF_CONC_CONNECTIONS]; 943 qdf_freq_t ml_freq_lst[MAX_NUMBER_OF_CONC_CONNECTIONS]; 944 uint8_t ml_linkid_lst[MAX_NUMBER_OF_CONC_CONNECTIONS]; 945 struct ml_link_info ml_link_info[MAX_NUMBER_OF_CONC_CONNECTIONS]; 946 uint8_t i = 0; 947 uint32_t scc_link_bitmap = 0; 948 949 ml_nlink_get_link_info(psoc, vdev, NLINK_EXCLUDE_REMOVED_LINK, 950 QDF_ARRAY_SIZE(ml_linkid_lst), 951 ml_link_info, ml_freq_lst, ml_vdev_lst, 952 ml_linkid_lst, &ml_num_link, 953 &ml_link_bitmap); 954 if (ml_num_link < 2) 955 return; 956 957 for (i = 0; i < ml_num_link; i++) { 958 /*todo add removed link to force_inactive_link_bitmap*/ 959 if (ml_freq_lst[i] == non_ml_sta_freq) { 960 scc_link_bitmap = 1 << ml_linkid_lst[i]; 961 } else if (policy_mgr_2_freq_always_on_same_mac( 962 psoc, ml_freq_lst[i], non_ml_sta_freq)) { 963 force_inactive_link_bitmap |= 1 << ml_linkid_lst[i]; 964 } else if (!wlan_cm_same_band_sta_allowed(psoc) && 965 (wlan_reg_is_24ghz_ch_freq(ml_freq_lst[i]) == 966 wlan_reg_is_24ghz_ch_freq(non_ml_sta_freq)) && 967 !policy_mgr_are_sbs_chan(psoc, ml_freq_lst[i], 968 non_ml_sta_freq)) { 969 force_inactive_link_bitmap |= 1 << ml_linkid_lst[i]; 970 } 971 } 972 973 /* If no left active link, don't send the force inactive command for 974 * concurrency purpose. 975 */ 976 if (!(ml_link_bitmap & ~force_inactive_link_bitmap)) { 977 mlo_debug("unexpected ML conc with legacy STA freq %d", 978 non_ml_sta_freq); 979 return; 980 } 981 982 if (force_inactive_link_bitmap) { 983 /* for example SBS rd, ML 2G+5G high, Legacy intf on 5G high, 984 * set force inactive with bitmap of 5g link. 985 * 986 * for SBS rd, ML 2G + 5G low + 6G, Legacy intf on 2G. 987 * set force inactive with bitmap 2G link, 988 * and set force inactive link num to 1 for left 5g and 6g 989 * link. 990 * for SBS rd, ML 2G + 5G low + 6G, Legacy intf on 5G low. 991 * set force inactive with bitmap 5G low link, 992 * and set force inactive link num to 1 for left 2g and 6g 993 * link. 994 * for SBS rd, ML 2G + 5G low + 6G, Legacy intf on 5G high. 995 * set force inactive with bitmap 6G link, 996 * and set force inactive link num to 1 for left 2g and 5g 997 * link. 998 * In above 3 link cases, if legacy intf is SCC with ml link 999 * don't force inactive by bitmap, only send force inactive 1000 * num with bitmap 1001 */ 1002 force_cmd->force_inactive_bitmap = force_inactive_link_bitmap; 1003 1004 affected_link_bitmap = 1005 ml_link_bitmap & ~force_inactive_link_bitmap; 1006 affected_link_bitmap &= ~scc_link_bitmap; 1007 force_cmd->force_inactive_num = 1008 convert_link_bitmap_to_link_ids( 1009 affected_link_bitmap, 0, NULL); 1010 if (force_cmd->force_inactive_num > 1) { 1011 force_cmd->force_inactive_num--; 1012 force_cmd->force_inactive_num_bitmap = 1013 affected_link_bitmap; 1014 1015 } else { 1016 force_cmd->force_inactive_num = 0; 1017 } 1018 } else { 1019 /* for example SBS rd, ML 2G+5G high, Legacy intf on 5G low, 1020 * set force inactive num to 1 with bitmap of 2g+5g link. 1021 * 1022 * for SBS rd, ML 2G + 5G low + 6G, Legacy intf on 5G low SCC. 1023 * set force inactive link num to 1 for left 2g and 6g 1024 * link. 1025 */ 1026 affected_link_bitmap = ml_link_bitmap; 1027 affected_link_bitmap &= ~scc_link_bitmap; 1028 1029 force_cmd->force_inactive_num = 1030 convert_link_bitmap_to_link_ids( 1031 affected_link_bitmap, 0, NULL); 1032 if (force_cmd->force_inactive_num > 1) { 1033 force_cmd->force_inactive_num--; 1034 force_cmd->force_inactive_num_bitmap = 1035 affected_link_bitmap; 1036 } else { 1037 force_cmd->force_inactive_num = 0; 1038 } 1039 } 1040 } 1041 1042 /** 1043 * ml_nlink_handle_legacy_sap_intf() - Check force inactive needed 1044 * with legacy SAP 1045 * @psoc: PSOC object information 1046 * @vdev: vdev object 1047 * @force_cmd: force command to be returned 1048 * @sap_vdev_id: legacy SAP vdev id 1049 * @sap_freq: legacy SAP channel frequency 1050 * 1051 * If legacy SAP is 2g only SAP and MLO STA is 5+6, 1052 * 2 links have to be force inactive with num 1. 1053 * 1054 * Return: void 1055 */ 1056 static void ml_nlink_handle_legacy_sap_intf(struct wlan_objmgr_psoc * psoc,struct wlan_objmgr_vdev * vdev,struct ml_link_force_state * force_cmd,uint8_t sap_vdev_id,qdf_freq_t sap_freq)1057 ml_nlink_handle_legacy_sap_intf(struct wlan_objmgr_psoc *psoc, 1058 struct wlan_objmgr_vdev *vdev, 1059 struct ml_link_force_state *force_cmd, 1060 uint8_t sap_vdev_id, 1061 qdf_freq_t sap_freq) 1062 { 1063 uint8_t ml_num_link = 0; 1064 uint32_t ml_link_bitmap = 0, affected_link_bitmap = 0; 1065 uint8_t ml_vdev_lst[MAX_NUMBER_OF_CONC_CONNECTIONS]; 1066 qdf_freq_t ml_freq_lst[MAX_NUMBER_OF_CONC_CONNECTIONS]; 1067 uint8_t ml_linkid_lst[MAX_NUMBER_OF_CONC_CONNECTIONS]; 1068 struct ml_link_info ml_link_info[MAX_NUMBER_OF_CONC_CONNECTIONS]; 1069 uint8_t i = 0; 1070 bool sap_2g_only = false; 1071 1072 /* SAP MCC with MLO STA link is not preferred. 1073 * If SAP is 2Ghz only by ACS and two ML link are 1074 * 5/6 band, then force SCC may not happen. In such 1075 * case inactive one link. 1076 */ 1077 if (policy_mgr_check_2ghz_only_sap_affected_link( 1078 psoc, sap_vdev_id, sap_freq, 1079 ml_num_link, ml_freq_lst)) { 1080 mlo_debug("2G only SAP vdev %d ch freq %d is not SCC with any MLO STA link", 1081 sap_vdev_id, sap_freq); 1082 sap_2g_only = true; 1083 } 1084 /* 1085 * If SAP is on 5G or 6G, SAP can always force SCC to 5G/6G ML STA or 1086 * 2G ML STA, no need force SCC link. 1087 */ 1088 if (!sap_2g_only) 1089 return; 1090 1091 ml_nlink_get_link_info(psoc, vdev, NLINK_EXCLUDE_REMOVED_LINK, 1092 QDF_ARRAY_SIZE(ml_linkid_lst), 1093 ml_link_info, ml_freq_lst, ml_vdev_lst, 1094 ml_linkid_lst, &ml_num_link, 1095 &ml_link_bitmap); 1096 if (ml_num_link < 2) 1097 return; 1098 1099 for (i = 0; i < ml_num_link; i++) { 1100 if (!wlan_reg_is_24ghz_ch_freq(ml_freq_lst[i])) 1101 affected_link_bitmap |= 1 << ml_linkid_lst[i]; 1102 } 1103 1104 if (affected_link_bitmap) { 1105 /* for SBS rd, ML 2G + 5G low, Legacy SAP on 2G. 1106 * no force any link 1107 * for SBS rd, ML 5G low + 5G high/6G, Legacy SAP on 2G. 1108 * set force inactive num 1 with bitmap 5g and 6g. 1109 * 1110 * for SBS rd, ML 2G + 5G low + 6G, Legacy SAP on 2G. 1111 * set force inactive link num to 1 for 5g and 6g 1112 * link. 1113 */ 1114 force_cmd->force_inactive_num = 1115 convert_link_bitmap_to_link_ids( 1116 affected_link_bitmap, 0, NULL); 1117 if (force_cmd->force_inactive_num > 1) { 1118 force_cmd->force_inactive_num--; 1119 force_cmd->force_inactive_num_bitmap = 1120 affected_link_bitmap; 1121 } else { 1122 force_cmd->force_inactive_num = 0; 1123 } 1124 } 1125 } 1126 1127 /** 1128 * ml_nlink_handle_legacy_p2p_intf() - Check force inactive needed 1129 * with p2p 1130 * @psoc: PSOC object information 1131 * @vdev: vdev object 1132 * @force_cmd: force command to be returned 1133 * @p2p_vdev_id: p2p vdev id 1134 * @p2p_freq: p2p channel frequency 1135 * 1136 * If P2P has low latency flag and MCC with any link of MLO STA, the mlo link 1137 * will be forced inactive. And if 3 link MLO case, the left 2 links have to 1138 * be force inactive with num 1. 1139 * 1140 * Return: void 1141 */ 1142 static void ml_nlink_handle_legacy_p2p_intf(struct wlan_objmgr_psoc * psoc,struct wlan_objmgr_vdev * vdev,struct ml_link_force_state * force_cmd,uint8_t p2p_vdev_id,qdf_freq_t p2p_freq)1143 ml_nlink_handle_legacy_p2p_intf(struct wlan_objmgr_psoc *psoc, 1144 struct wlan_objmgr_vdev *vdev, 1145 struct ml_link_force_state *force_cmd, 1146 uint8_t p2p_vdev_id, 1147 qdf_freq_t p2p_freq) 1148 { 1149 uint8_t ml_num_link = 0; 1150 uint32_t ml_link_bitmap = 0, affected_link_bitmap = 0; 1151 uint32_t force_inactive_link_bitmap = 0; 1152 uint8_t ml_vdev_lst[MAX_NUMBER_OF_CONC_CONNECTIONS]; 1153 qdf_freq_t ml_freq_lst[MAX_NUMBER_OF_CONC_CONNECTIONS]; 1154 uint8_t ml_linkid_lst[MAX_NUMBER_OF_CONC_CONNECTIONS]; 1155 struct ml_link_info ml_link_info[MAX_NUMBER_OF_CONC_CONNECTIONS]; 1156 uint8_t i = 0; 1157 uint32_t scc_link_bitmap = 0; 1158 1159 /* If high tput or low latency is not set, mcc is allowed for p2p */ 1160 if (!policy_mgr_is_vdev_high_tput_or_low_latency( 1161 psoc, p2p_vdev_id)) 1162 return; 1163 ml_nlink_get_link_info(psoc, vdev, NLINK_EXCLUDE_REMOVED_LINK, 1164 QDF_ARRAY_SIZE(ml_linkid_lst), 1165 ml_link_info, ml_freq_lst, ml_vdev_lst, 1166 ml_linkid_lst, &ml_num_link, 1167 &ml_link_bitmap); 1168 if (ml_num_link < 2) 1169 return; 1170 1171 for (i = 0; i < ml_num_link; i++) { 1172 if (ml_freq_lst[i] == p2p_freq) { 1173 scc_link_bitmap = 1 << ml_linkid_lst[i]; 1174 } else if (policy_mgr_2_freq_always_on_same_mac( 1175 psoc, ml_freq_lst[i], p2p_freq)) { 1176 force_inactive_link_bitmap |= 1 << ml_linkid_lst[i]; 1177 } 1178 } 1179 /* If no left active link, don't send the force inactive command for 1180 * concurrency purpose. 1181 */ 1182 if (!(ml_link_bitmap & ~force_inactive_link_bitmap)) { 1183 mlo_debug("unexpected ML conc with legacy P2P freq %d", 1184 p2p_freq); 1185 return; 1186 } 1187 1188 if (force_inactive_link_bitmap) { 1189 /* for example SBS rd, ML 2G+5G high, Legacy intf on 5G high, 1190 * set force inactive with bitmap of 5g link. 1191 * 1192 * for SBS rd, ML 2G + 5G low + 6G, Legacy intf on 2G. 1193 * set force inactive with bitmap 2G link, 1194 * and set force inactive link num to 1 for left 5g and 6g 1195 * link. 1196 * for SBS rd, ML 2G + 5G low + 6G, Legacy intf on 5G low. 1197 * set force inactive with bitmap 5G low link, 1198 * and set force inactive link num to 1 for left 2g and 6g 1199 * link. 1200 * for SBS rd, ML 2G + 5G low + 6G, Legacy intf on 5G high.. 1201 * set force inactive with bitmap 6G low link, 1202 * and set force inactive link num to 1 for left 2g and 5g 1203 * link. 1204 */ 1205 force_cmd->force_inactive_bitmap = force_inactive_link_bitmap; 1206 1207 affected_link_bitmap = 1208 ml_link_bitmap & ~force_inactive_link_bitmap; 1209 affected_link_bitmap &= ~scc_link_bitmap; 1210 force_cmd->force_inactive_num = 1211 convert_link_bitmap_to_link_ids( 1212 affected_link_bitmap, 0, NULL); 1213 if (force_cmd->force_inactive_num > 1) { 1214 force_cmd->force_inactive_num--; 1215 force_cmd->force_inactive_num_bitmap = 1216 affected_link_bitmap; 1217 1218 } else { 1219 force_cmd->force_inactive_num = 0; 1220 } 1221 } else { 1222 /* for example SBS rd, ML 2G+5G high, Legacy intf on 5G low, 1223 * set force inactive num to 1 with bitmap of 2g+5g link. 1224 * 1225 * for SBS rd, ML 2G + 5G low + 6G, Legacy intf on 5G low SCC. 1226 * set force inactive link num to 1 for left 2g and 6g 1227 * link. 1228 */ 1229 affected_link_bitmap = ml_link_bitmap; 1230 affected_link_bitmap &= ~scc_link_bitmap; 1231 1232 force_cmd->force_inactive_num = 1233 convert_link_bitmap_to_link_ids( 1234 affected_link_bitmap, 0, NULL); 1235 if (force_cmd->force_inactive_num > 1) { 1236 force_cmd->force_inactive_num--; 1237 force_cmd->force_inactive_num_bitmap = 1238 affected_link_bitmap; 1239 } else { 1240 force_cmd->force_inactive_num = 0; 1241 } 1242 } 1243 } 1244 1245 /** 1246 * ml_nlink_handle_3_port_specific_scenario() - Check some specific corner 1247 * case that can't be handled general logic in 1248 * ml_nlink_handle_legacy_intf_3_ports. 1249 * @psoc: PSOC object information 1250 * @legacy_intf_freq1: legacy interface 1 channel frequency 1251 * @legacy_intf_freq2: legacy interface 2 channel frequency 1252 * @ml_num_link: number of ML STA links 1253 * @ml_freq_lst: ML STA link channel frequency list 1254 * @ml_linkid_lst: ML STA link ids 1255 * 1256 * Return: link force inactive bitmap 1257 */ 1258 static uint32_t ml_nlink_handle_3_port_specific_scenario(struct wlan_objmgr_psoc * psoc,qdf_freq_t legacy_intf_freq1,qdf_freq_t legacy_intf_freq2,uint8_t ml_num_link,qdf_freq_t * ml_freq_lst,uint8_t * ml_linkid_lst)1259 ml_nlink_handle_3_port_specific_scenario(struct wlan_objmgr_psoc *psoc, 1260 qdf_freq_t legacy_intf_freq1, 1261 qdf_freq_t legacy_intf_freq2, 1262 uint8_t ml_num_link, 1263 qdf_freq_t *ml_freq_lst, 1264 uint8_t *ml_linkid_lst) 1265 { 1266 uint32_t force_inactive_link_bitmap = 0; 1267 1268 if (ml_num_link < 2) 1269 return 0; 1270 1271 /* special case handling: 1272 * LL P2P on 2.4G, ML STA 5G+6G, SAP on 6G, then 1273 * inactive 5G link. 1274 * LL P2P on 2.4G, ML STA 5G+6G, SAP on 5G, then 1275 * inactive 6G link. 1276 */ 1277 if (WLAN_REG_IS_24GHZ_CH_FREQ(legacy_intf_freq1) && 1278 !WLAN_REG_IS_24GHZ_CH_FREQ(ml_freq_lst[0]) && 1279 policy_mgr_are_sbs_chan(psoc, ml_freq_lst[0], ml_freq_lst[1]) && 1280 policy_mgr_2_freq_always_on_same_mac(psoc, ml_freq_lst[0], 1281 legacy_intf_freq2)) 1282 force_inactive_link_bitmap |= 1 << ml_linkid_lst[1]; 1283 else if (WLAN_REG_IS_24GHZ_CH_FREQ(legacy_intf_freq1) && 1284 !WLAN_REG_IS_24GHZ_CH_FREQ(ml_freq_lst[1]) && 1285 policy_mgr_are_sbs_chan(psoc, ml_freq_lst[0], 1286 ml_freq_lst[1]) && 1287 policy_mgr_2_freq_always_on_same_mac(psoc, ml_freq_lst[1], 1288 legacy_intf_freq2)) 1289 force_inactive_link_bitmap |= 1 << ml_linkid_lst[0]; 1290 1291 if (force_inactive_link_bitmap) 1292 mlo_debug("force inactive 0x%x", force_inactive_link_bitmap); 1293 1294 return force_inactive_link_bitmap; 1295 } 1296 1297 /** 1298 * ml_nlink_handle_legacy_intf_3_ports() - Check force inactive needed 1299 * with 2 legacy interfaces 1300 * @psoc: PSOC object information 1301 * @vdev: vdev object 1302 * @force_cmd: force command to be returned 1303 * @legacy_intf_freq1: legacy interface frequency 1304 * @legacy_intf_freq2: legacy interface frequency 1305 * 1306 * If legacy interface 1 (which channel frequency legacy_intf_freq1) is 1307 * mcc with any link based on current hw mode, then force inactive the link. 1308 * And if standby link is mcc with legacy interface, then disable standby 1309 * link as well. 1310 * In 3 Port case, at present only legacy interface 1(which channel frequency 1311 * legacy_intf_freq1) MCC avoidance requirement can be met. The assignment of 1312 * legacy_intf_freq1 and legacy_intf_freq2 is based on priority of Port type, 1313 * check policy_mgr_get_legacy_conn_info for detail. 1314 * Cornor cases will be handled in ml_nlink_handle_3_port_specific_scenario. 1315 * 1316 * Return: void 1317 */ 1318 static void ml_nlink_handle_legacy_intf_3_ports(struct wlan_objmgr_psoc * psoc,struct wlan_objmgr_vdev * vdev,struct ml_link_force_state * force_cmd,qdf_freq_t legacy_intf_freq1,qdf_freq_t legacy_intf_freq2)1319 ml_nlink_handle_legacy_intf_3_ports(struct wlan_objmgr_psoc *psoc, 1320 struct wlan_objmgr_vdev *vdev, 1321 struct ml_link_force_state *force_cmd, 1322 qdf_freq_t legacy_intf_freq1, 1323 qdf_freq_t legacy_intf_freq2) 1324 { 1325 uint8_t ml_num_link = 0; 1326 uint32_t ml_link_bitmap = 0; 1327 uint32_t force_inactive_link_bitmap = 0; 1328 uint8_t ml_vdev_lst[MAX_NUMBER_OF_CONC_CONNECTIONS]; 1329 qdf_freq_t ml_freq_lst[MAX_NUMBER_OF_CONC_CONNECTIONS]; 1330 uint8_t ml_linkid_lst[MAX_NUMBER_OF_CONC_CONNECTIONS]; 1331 struct ml_link_info ml_link_info[MAX_NUMBER_OF_CONC_CONNECTIONS]; 1332 uint8_t i = 0; 1333 uint32_t scc_link_bitmap = 0; 1334 1335 ml_nlink_get_link_info(psoc, vdev, NLINK_EXCLUDE_REMOVED_LINK, 1336 QDF_ARRAY_SIZE(ml_linkid_lst), 1337 ml_link_info, ml_freq_lst, ml_vdev_lst, 1338 ml_linkid_lst, &ml_num_link, 1339 &ml_link_bitmap); 1340 if (ml_num_link < 2) 1341 return; 1342 1343 for (i = 0; i < ml_num_link; i++) { 1344 if (ml_vdev_lst[i] == WLAN_INVALID_VDEV_ID) { 1345 /*standby link will be handled later. */ 1346 continue; 1347 } 1348 if (ml_freq_lst[i] == legacy_intf_freq1) { 1349 scc_link_bitmap = 1 << ml_linkid_lst[i]; 1350 if (ml_freq_lst[i] == legacy_intf_freq2) { 1351 mlo_debug("3 vdev scc no-op"); 1352 return; 1353 } 1354 } else if (policy_mgr_are_2_freq_on_same_mac( 1355 psoc, ml_freq_lst[i], legacy_intf_freq1)) { 1356 force_inactive_link_bitmap |= 1 << ml_linkid_lst[i]; 1357 } else if (i == 1) { 1358 force_inactive_link_bitmap |= 1359 ml_nlink_handle_3_port_specific_scenario( 1360 psoc, 1361 legacy_intf_freq1, 1362 legacy_intf_freq2, 1363 ml_num_link, 1364 ml_freq_lst, 1365 ml_linkid_lst); 1366 } 1367 } 1368 /* usually it can't happen in 3 Port */ 1369 if (!force_inactive_link_bitmap && !scc_link_bitmap) { 1370 mlo_debug("legacy vdev freq %d standalone on dedicated mac", 1371 legacy_intf_freq1); 1372 return; 1373 } 1374 1375 if (force_inactive_link_bitmap) 1376 force_cmd->force_inactive_bitmap = force_inactive_link_bitmap; 1377 } 1378 1379 static void ml_nlink_handle_standby_link_3_ports(struct wlan_objmgr_psoc * psoc,struct wlan_objmgr_vdev * vdev,struct ml_link_force_state * force_cmd,uint8_t num_legacy_vdev,uint8_t * vdev_lst,qdf_freq_t * freq_lst,enum policy_mgr_con_mode * mode_lst)1380 ml_nlink_handle_standby_link_3_ports( 1381 struct wlan_objmgr_psoc *psoc, 1382 struct wlan_objmgr_vdev *vdev, 1383 struct ml_link_force_state *force_cmd, 1384 uint8_t num_legacy_vdev, 1385 uint8_t *vdev_lst, 1386 qdf_freq_t *freq_lst, 1387 enum policy_mgr_con_mode *mode_lst) 1388 { 1389 uint8_t ml_num_link = 0; 1390 uint32_t ml_link_bitmap = 0; 1391 uint32_t force_inactive_link_bitmap = 0; 1392 uint8_t ml_vdev_lst[MAX_NUMBER_OF_CONC_CONNECTIONS]; 1393 qdf_freq_t ml_freq_lst[MAX_NUMBER_OF_CONC_CONNECTIONS]; 1394 uint8_t ml_linkid_lst[MAX_NUMBER_OF_CONC_CONNECTIONS]; 1395 struct ml_link_info ml_link_info[MAX_NUMBER_OF_CONC_CONNECTIONS]; 1396 uint8_t i, j; 1397 1398 if (num_legacy_vdev < 2) 1399 return; 1400 1401 ml_nlink_get_link_info(psoc, vdev, NLINK_EXCLUDE_REMOVED_LINK, 1402 QDF_ARRAY_SIZE(ml_linkid_lst), 1403 ml_link_info, ml_freq_lst, ml_vdev_lst, 1404 ml_linkid_lst, &ml_num_link, 1405 &ml_link_bitmap); 1406 if (ml_num_link < 2) 1407 return; 1408 for (i = 0; i < ml_num_link; i++) { 1409 if (ml_vdev_lst[i] != WLAN_INVALID_VDEV_ID) 1410 continue; 1411 /* standby link will be forced inactive if mcc with 1412 * legacy interface 1413 */ 1414 for (j = 0; j < num_legacy_vdev; j++) { 1415 if (ml_freq_lst[i] != freq_lst[j] && 1416 policy_mgr_are_2_freq_on_same_mac( 1417 psoc, ml_freq_lst[i], freq_lst[j])) 1418 force_inactive_link_bitmap |= 1419 1 << ml_linkid_lst[i]; 1420 } 1421 } 1422 1423 if (force_inactive_link_bitmap) 1424 force_cmd->force_inactive_bitmap |= force_inactive_link_bitmap; 1425 } 1426 1427 /** 1428 * ml_nlink_handle_legacy_intf() - Check force inactive needed 1429 * with legacy interface 1430 * @psoc: PSOC object information 1431 * @vdev: vdev object 1432 * @force_cmd: force command to be returned 1433 * 1434 * Return: void 1435 */ 1436 static void ml_nlink_handle_legacy_intf(struct wlan_objmgr_psoc * psoc,struct wlan_objmgr_vdev * vdev,struct ml_link_force_state * force_cmd)1437 ml_nlink_handle_legacy_intf(struct wlan_objmgr_psoc *psoc, 1438 struct wlan_objmgr_vdev *vdev, 1439 struct ml_link_force_state *force_cmd) 1440 { 1441 uint8_t vdev_lst[MAX_NUMBER_OF_CONC_CONNECTIONS]; 1442 qdf_freq_t freq_lst[MAX_NUMBER_OF_CONC_CONNECTIONS]; 1443 enum policy_mgr_con_mode mode_lst[MAX_NUMBER_OF_CONC_CONNECTIONS]; 1444 uint8_t num_legacy_vdev; 1445 1446 num_legacy_vdev = policy_mgr_get_legacy_conn_info( 1447 psoc, vdev_lst, 1448 freq_lst, mode_lst, 1449 QDF_ARRAY_SIZE(vdev_lst)); 1450 if (!num_legacy_vdev) 1451 return; 1452 /* 2 port case with 2 ml sta links or 1453 * 2 port case with 3 ml sta links 1454 */ 1455 if (num_legacy_vdev == 1) { 1456 switch (mode_lst[0]) { 1457 case PM_STA_MODE: 1458 ml_nlink_handle_legacy_sta_intf( 1459 psoc, vdev, force_cmd, vdev_lst[0], 1460 freq_lst[0]); 1461 break; 1462 case PM_SAP_MODE: 1463 ml_nlink_handle_legacy_sap_intf( 1464 psoc, vdev, force_cmd, vdev_lst[0], 1465 freq_lst[0]); 1466 break; 1467 case PM_P2P_CLIENT_MODE: 1468 case PM_P2P_GO_MODE: 1469 ml_nlink_handle_legacy_p2p_intf( 1470 psoc, vdev, force_cmd, vdev_lst[0], 1471 freq_lst[0]); 1472 break; 1473 default: 1474 /* unexpected legacy connection count */ 1475 mlo_debug("unexpected legacy intf mode %d", 1476 mode_lst[0]); 1477 return; 1478 } 1479 ml_nlink_dump_force_state(force_cmd, ""); 1480 return; 1481 } 1482 /* 3 ports case with ml sta 2 or 3 links, suppose port 3 vdev is 1483 * low latency legacy vdev: 1484 * 6G: ML Link + Port2 + Port3 | 5G: ML Link 1485 * => no op 1486 * 6G: ML Link + Port2 | 5G: ML Link + Port3 1487 * => disable 5G link if 5G mcc 1488 * 6G: ML Link + Port3 | 5G: ML Link + Port2 1489 * => disable 6G link if 6G mcc 1490 * 6G: ML Link | 5G: ML Link + Port3 | 2G: Port2 1491 * => disable 5G link if 5G mcc. 1492 * 6G: ML Link | 5G: ML Link + Port2 | 2G: Port3 1493 * => disable 6g link. 1494 * 6G: ML Link + Port3 | 5G: ML Link | 2G: Port2 1495 * => disable 6G link if 6G mcc. 1496 * 6G: ML Link + Port2 | 5G: ML Link | 2G: Port3 1497 * => disable 6g link. 1498 * 6G: ML Link + Port2 + Port3 | 2G: ML Link 1499 * => no op 1500 * 6G: ML Link + Port2 | 2G: ML Link + Port3 1501 * => disable 2G link if 2G mcc 1502 * 6G: ML Link + Port3 | 2G: ML Link + Port2 1503 * => disable 6G link if 6G mcc 1504 * 6G: ML Link | 2G: ML Link + Port3 | 5G: Port2 1505 * => disable 2G link if 2G mcc. 1506 * 6G: ML Link | 2G: ML Link + Port2 | 5GL: Port3 1507 * => disable 6G link 1508 * 6G: ML Link + Port3 | 2G: ML Link | 5G: Port2 1509 * => disable 6G link if 6G mcc. 1510 * 6G: ML Link + Port2 | 2G: ML Link | 5GL: Port3 1511 * => disable 2G link 1512 * general rule: 1513 * If Port3 is mcc with any link based on current hw mode, then 1514 * force inactive the link. 1515 * And if standby link is mcc with Port3, then disable standby 1516 * link as well. 1517 */ 1518 switch (mode_lst[0]) { 1519 case PM_P2P_CLIENT_MODE: 1520 case PM_P2P_GO_MODE: 1521 if (!policy_mgr_is_vdev_high_tput_or_low_latency( 1522 psoc, vdev_lst[0])) 1523 break; 1524 fallthrough; 1525 case PM_STA_MODE: 1526 ml_nlink_handle_legacy_intf_3_ports( 1527 psoc, vdev, force_cmd, freq_lst[0], freq_lst[1]); 1528 break; 1529 case PM_SAP_MODE: 1530 /* if 2g only sap present, force inactive num to fw. */ 1531 ml_nlink_handle_legacy_sap_intf( 1532 psoc, vdev, force_cmd, vdev_lst[0], freq_lst[0]); 1533 break; 1534 default: 1535 /* unexpected legacy connection count */ 1536 mlo_debug("unexpected legacy intf mode %d", mode_lst[0]); 1537 return; 1538 } 1539 ml_nlink_handle_standby_link_3_ports(psoc, vdev, force_cmd, 1540 num_legacy_vdev, 1541 vdev_lst, 1542 freq_lst, 1543 mode_lst); 1544 ml_nlink_dump_force_state(force_cmd, ""); 1545 } 1546 1547 /** 1548 * ml_nlink_handle_dynamic_inactive() - Handle dynamic force inactive num 1549 * with legacy SAP 1550 * @psoc: PSOC object information 1551 * @vdev: vdev object 1552 * @curr: current force command state 1553 * @new: new force command 1554 * 1555 * If ML STA 2 or 3 links are present and force inactive num = 1 with dynamic 1556 * flag enabled for some reason, FW will report the current inactive links, 1557 * host will select one and save to curr_dynamic_inactive_bitmap. 1558 * If SAP starting on channel which is same mac as links in 1559 * the curr_dynamic_inactive_bitmap, host will force inactive the links in 1560 * curr_dynamic_inactive_bitmap to avoid FW link switch between the dynamic 1561 * inactive links. 1562 * 1563 * Return: void 1564 */ 1565 static void ml_nlink_handle_dynamic_inactive(struct wlan_objmgr_psoc * psoc,struct wlan_objmgr_vdev * vdev,struct ml_link_force_state * curr,struct ml_link_force_state * new)1566 ml_nlink_handle_dynamic_inactive(struct wlan_objmgr_psoc *psoc, 1567 struct wlan_objmgr_vdev *vdev, 1568 struct ml_link_force_state *curr, 1569 struct ml_link_force_state *new) 1570 { 1571 uint8_t vdev_lst[MAX_NUMBER_OF_CONC_CONNECTIONS]; 1572 qdf_freq_t freq_lst[MAX_NUMBER_OF_CONC_CONNECTIONS]; 1573 enum policy_mgr_con_mode mode_lst[MAX_NUMBER_OF_CONC_CONNECTIONS]; 1574 uint8_t num; 1575 uint8_t ml_num_link = 0; 1576 uint32_t ml_link_bitmap; 1577 uint32_t force_inactive_link_bitmap = 0; 1578 uint8_t ml_vdev_lst[MAX_NUMBER_OF_CONC_CONNECTIONS]; 1579 qdf_freq_t ml_freq_lst[MAX_NUMBER_OF_CONC_CONNECTIONS]; 1580 uint8_t ml_linkid_lst[MAX_NUMBER_OF_CONC_CONNECTIONS]; 1581 struct ml_link_info ml_link_info[MAX_NUMBER_OF_CONC_CONNECTIONS]; 1582 uint32_t i, j; 1583 1584 /* If force inactive num wasn't sent to fw, no need to handle 1585 * dynamic inactive links. 1586 */ 1587 if (!curr->force_inactive_num || 1588 !curr->force_inactive_num_bitmap || 1589 !curr->curr_dynamic_inactive_bitmap) 1590 return; 1591 if (curr->force_inactive_num != new->force_inactive_num || 1592 curr->force_inactive_num_bitmap != 1593 new->force_inactive_num_bitmap) 1594 return; 1595 /* If links have been forced inactive by bitmap, no need to force 1596 * again. 1597 */ 1598 if ((new->force_inactive_bitmap & 1599 curr->curr_dynamic_inactive_bitmap) == 1600 curr->curr_dynamic_inactive_bitmap) 1601 return; 1602 1603 num = policy_mgr_get_legacy_conn_info( 1604 psoc, vdev_lst, 1605 freq_lst, mode_lst, 1606 QDF_ARRAY_SIZE(vdev_lst)); 1607 if (!num) 1608 return; 1609 ml_nlink_get_link_info(psoc, vdev, NLINK_EXCLUDE_REMOVED_LINK, 1610 QDF_ARRAY_SIZE(ml_linkid_lst), 1611 ml_link_info, ml_freq_lst, ml_vdev_lst, 1612 ml_linkid_lst, &ml_num_link, 1613 &ml_link_bitmap); 1614 if (ml_num_link < 2) 1615 return; 1616 for (i = 0; i < ml_num_link; i++) { 1617 if (!((1 << ml_linkid_lst[i]) & 1618 curr->curr_dynamic_inactive_bitmap)) 1619 continue; 1620 for (j = 0; j < num; j++) { 1621 if (mode_lst[j] != PM_SAP_MODE) 1622 continue; 1623 if (policy_mgr_2_freq_always_on_same_mac( 1624 psoc, freq_lst[j], ml_freq_lst[i])) { 1625 force_inactive_link_bitmap |= 1626 1 << ml_linkid_lst[i]; 1627 mlo_debug("force dynamic inactive link id %d freq %d for sap freq %d", 1628 ml_linkid_lst[i], ml_freq_lst[i], 1629 freq_lst[j]); 1630 } else if (num > 1 && 1631 policy_mgr_are_2_freq_on_same_mac( 1632 psoc, freq_lst[j], ml_freq_lst[i])) { 1633 force_inactive_link_bitmap |= 1634 1 << ml_linkid_lst[i]; 1635 mlo_debug("force dynamic inactive link id %d freq %d for sap freq %d", 1636 ml_linkid_lst[i], ml_freq_lst[i], 1637 freq_lst[j]); 1638 } 1639 } 1640 } 1641 if (force_inactive_link_bitmap) { 1642 new->force_inactive_bitmap |= force_inactive_link_bitmap; 1643 ml_nlink_dump_force_state(new, ""); 1644 } 1645 } 1646 1647 /** 1648 * ml_nlink_sta_inactivity_allowed_with_quiet() - Check force inactive allowed 1649 * for links in bitmap 1650 * @psoc: PSOC object information 1651 * @vdev: vdev object 1652 * @force_inactive_bitmap: force inactive link bimap 1653 * 1654 * If left links (exclude removed link and QUITE link) are zero, the force 1655 * inactive bitmap is not allowed. 1656 * 1657 * Return: true if allow to force inactive links in force_inactive_bitmap 1658 */ ml_nlink_sta_inactivity_allowed_with_quiet(struct wlan_objmgr_psoc * psoc,struct wlan_objmgr_vdev * vdev,uint16_t force_inactive_bitmap)1659 static bool ml_nlink_sta_inactivity_allowed_with_quiet( 1660 struct wlan_objmgr_psoc *psoc, 1661 struct wlan_objmgr_vdev *vdev, 1662 uint16_t force_inactive_bitmap) 1663 { 1664 uint8_t ml_num_link = 0; 1665 uint32_t ml_link_bitmap = 0; 1666 uint8_t ml_vdev_lst[MAX_NUMBER_OF_CONC_CONNECTIONS]; 1667 qdf_freq_t ml_freq_lst[MAX_NUMBER_OF_CONC_CONNECTIONS]; 1668 uint8_t ml_linkid_lst[MAX_NUMBER_OF_CONC_CONNECTIONS]; 1669 struct ml_link_info ml_link_info[MAX_NUMBER_OF_CONC_CONNECTIONS]; 1670 1671 ml_nlink_get_link_info(psoc, vdev, (NLINK_EXCLUDE_REMOVED_LINK | 1672 NLINK_EXCLUDE_QUIET_LINK | 1673 NLINK_EXCLUDE_STANDBY_LINK), 1674 QDF_ARRAY_SIZE(ml_linkid_lst), 1675 ml_link_info, ml_freq_lst, ml_vdev_lst, 1676 ml_linkid_lst, &ml_num_link, 1677 &ml_link_bitmap); 1678 ml_link_bitmap &= ~force_inactive_bitmap; 1679 if (!ml_link_bitmap) { 1680 mlo_debug("not allow - no active link after force inactive 0x%x", 1681 force_inactive_bitmap); 1682 return false; 1683 } 1684 1685 return true; 1686 } 1687 1688 /** 1689 * ml_nlink_allow_conc() - Check force inactive allowed for links in bitmap 1690 * @psoc: PSOC object information 1691 * @vdev: vdev object 1692 * @no_forced_bitmap: no force link bitmap 1693 * @force_inactive_bitmap: force inactive link bimap 1694 * 1695 * Check the no force bitmap and force inactive bitmap are allowed to send 1696 * to firmware 1697 * 1698 * Return: true if allow to "no force" and force inactive links. 1699 */ 1700 static bool ml_nlink_allow_conc(struct wlan_objmgr_psoc * psoc,struct wlan_objmgr_vdev * vdev,uint16_t no_forced_bitmap,uint16_t force_inactive_bitmap)1701 ml_nlink_allow_conc(struct wlan_objmgr_psoc *psoc, 1702 struct wlan_objmgr_vdev *vdev, 1703 uint16_t no_forced_bitmap, 1704 uint16_t force_inactive_bitmap) 1705 { 1706 uint8_t vdev_id_num = 0; 1707 uint8_t vdev_ids[MAX_NUMBER_OF_CONC_CONNECTIONS]; 1708 uint32_t vdev_id_bitmap_sz; 1709 uint32_t vdev_id_bitmap[MLO_VDEV_BITMAP_SZ]; 1710 uint32_t i; 1711 union conc_ext_flag conc_ext_flags; 1712 struct wlan_objmgr_vdev *ml_vdev; 1713 bool allow = true; 1714 qdf_freq_t freq = 0; 1715 struct wlan_channel *bss_chan; 1716 1717 if (!ml_nlink_sta_inactivity_allowed_with_quiet( 1718 psoc, vdev, force_inactive_bitmap)) 1719 return false; 1720 1721 ml_nlink_convert_linkid_bitmap_to_vdev_bitmap( 1722 psoc, vdev, no_forced_bitmap, NULL, &vdev_id_bitmap_sz, 1723 vdev_id_bitmap, &vdev_id_num, vdev_ids); 1724 1725 for (i = 0; i < vdev_id_num; i++) { 1726 ml_vdev = 1727 wlan_objmgr_get_vdev_by_id_from_psoc(psoc, 1728 vdev_ids[i], 1729 WLAN_MLO_MGR_ID); 1730 if (!ml_vdev) { 1731 mlo_err("invalid vdev id %d ", vdev_ids[i]); 1732 continue; 1733 } 1734 1735 /* If link is active, no need to check allow conc */ 1736 if (!policy_mgr_vdev_is_force_inactive(psoc, vdev_ids[i])) { 1737 wlan_objmgr_vdev_release_ref(ml_vdev, 1738 WLAN_MLO_MGR_ID); 1739 continue; 1740 } 1741 1742 conc_ext_flags.value = 1743 policy_mgr_get_conc_ext_flags(ml_vdev, true); 1744 1745 bss_chan = wlan_vdev_mlme_get_bss_chan(ml_vdev); 1746 if (bss_chan) 1747 freq = bss_chan->ch_freq; 1748 1749 if (!policy_mgr_is_concurrency_allowed(psoc, PM_STA_MODE, 1750 freq, 1751 HW_MODE_20_MHZ, 1752 conc_ext_flags.value, 1753 NULL)) { 1754 wlan_objmgr_vdev_release_ref(ml_vdev, 1755 WLAN_MLO_MGR_ID); 1756 break; 1757 } 1758 1759 wlan_objmgr_vdev_release_ref(ml_vdev, WLAN_MLO_MGR_ID); 1760 } 1761 1762 if (i < vdev_id_num) { 1763 mlo_err("not allow - vdev %d freq %d active due to conc", 1764 vdev_ids[i], freq); 1765 allow = false; 1766 } 1767 1768 return allow; 1769 } 1770 1771 static QDF_STATUS ml_nlink_update_no_force_for_all(struct wlan_objmgr_psoc * psoc,struct wlan_objmgr_vdev * vdev,struct ml_link_force_state * curr,struct ml_link_force_state * new,enum mlo_link_force_reason reason)1772 ml_nlink_update_no_force_for_all(struct wlan_objmgr_psoc *psoc, 1773 struct wlan_objmgr_vdev *vdev, 1774 struct ml_link_force_state *curr, 1775 struct ml_link_force_state *new, 1776 enum mlo_link_force_reason reason) 1777 { 1778 uint16_t no_force_links; 1779 QDF_STATUS status = QDF_STATUS_SUCCESS; 1780 1781 /* Special handling for clear all force mode in target. 1782 * send MLO_LINK_FORCE_MODE_NO_FORCE to clear "all" 1783 * to target 1784 */ 1785 if (!new->force_inactive_bitmap && 1786 !new->force_inactive_num && 1787 !new->force_active_bitmap && 1788 !new->force_active_num && 1789 (curr->force_inactive_bitmap || 1790 curr->force_inactive_num || 1791 curr->force_active_bitmap || 1792 curr->force_active_num)) { 1793 /* If link is force inactive already, but new command will 1794 * mark it non-force, need to check conc allow or not. 1795 */ 1796 no_force_links = curr->force_inactive_bitmap; 1797 /* Check non forced links allowed by conc */ 1798 if (!ml_nlink_allow_conc(psoc, vdev, no_force_links, 0)) { 1799 status = QDF_STATUS_E_INVAL; 1800 goto end; 1801 } 1802 1803 status = policy_mgr_mlo_sta_set_nlink( 1804 psoc, wlan_vdev_get_id(vdev), 1805 reason, 1806 MLO_LINK_FORCE_MODE_NO_FORCE, 1807 0, 0, 0, 0); 1808 } 1809 1810 end: 1811 return status; 1812 } 1813 1814 static QDF_STATUS ml_nlink_update_force_inactive(struct wlan_objmgr_psoc * psoc,struct wlan_objmgr_vdev * vdev,struct ml_link_force_state * curr,struct ml_link_force_state * new,enum mlo_link_force_reason reason)1815 ml_nlink_update_force_inactive(struct wlan_objmgr_psoc *psoc, 1816 struct wlan_objmgr_vdev *vdev, 1817 struct ml_link_force_state *curr, 1818 struct ml_link_force_state *new, 1819 enum mlo_link_force_reason reason) 1820 { 1821 uint16_t no_force_links; 1822 QDF_STATUS status = QDF_STATUS_SUCCESS; 1823 1824 if (new->force_inactive_bitmap != curr->force_inactive_bitmap) { 1825 /* If link is force inactive already, but new command will 1826 * mark it non-force, need to check conc allow or not. 1827 */ 1828 no_force_links = curr->force_inactive_bitmap & 1829 new->force_inactive_bitmap; 1830 no_force_links ^= curr->force_inactive_bitmap; 1831 1832 /* Check non forced links allowed by conc */ 1833 if (!ml_nlink_allow_conc(psoc, vdev, no_force_links, 1834 new->force_inactive_bitmap)) { 1835 status = QDF_STATUS_E_NOSUPPORT; 1836 goto end; 1837 } 1838 status = policy_mgr_mlo_sta_set_nlink( 1839 psoc, wlan_vdev_get_id(vdev), reason, 1840 MLO_LINK_FORCE_MODE_INACTIVE, 1841 0, 1842 new->force_inactive_bitmap, 1843 0, 1844 link_ctrl_f_overwrite_inactive_bitmap | 1845 link_ctrl_f_post_re_evaluate); 1846 } 1847 1848 end: 1849 return status; 1850 } 1851 1852 static QDF_STATUS ml_nlink_update_force_inactive_num(struct wlan_objmgr_psoc * psoc,struct wlan_objmgr_vdev * vdev,struct ml_link_force_state * curr,struct ml_link_force_state * new,enum mlo_link_force_reason reason)1853 ml_nlink_update_force_inactive_num(struct wlan_objmgr_psoc *psoc, 1854 struct wlan_objmgr_vdev *vdev, 1855 struct ml_link_force_state *curr, 1856 struct ml_link_force_state *new, 1857 enum mlo_link_force_reason reason) 1858 { 1859 QDF_STATUS status = QDF_STATUS_SUCCESS; 1860 1861 if (new->force_inactive_num != 1862 curr->force_inactive_num || 1863 new->force_inactive_num_bitmap != 1864 curr->force_inactive_num_bitmap) { 1865 status = policy_mgr_mlo_sta_set_nlink( 1866 psoc, wlan_vdev_get_id(vdev), reason, 1867 MLO_LINK_FORCE_MODE_INACTIVE_NUM, 1868 new->force_inactive_num, 1869 new->force_inactive_num_bitmap, 1870 0, 1871 link_ctrl_f_dynamic_force_link_num | 1872 link_ctrl_f_post_re_evaluate); 1873 } 1874 1875 return status; 1876 } 1877 1878 static QDF_STATUS ml_nlink_update_force_active(struct wlan_objmgr_psoc * psoc,struct wlan_objmgr_vdev * vdev,struct ml_link_force_state * curr,struct ml_link_force_state * new,enum mlo_link_force_reason reason)1879 ml_nlink_update_force_active(struct wlan_objmgr_psoc *psoc, 1880 struct wlan_objmgr_vdev *vdev, 1881 struct ml_link_force_state *curr, 1882 struct ml_link_force_state *new, 1883 enum mlo_link_force_reason reason) 1884 { 1885 return QDF_STATUS_SUCCESS; 1886 } 1887 1888 static QDF_STATUS ml_nlink_update_force_active_num(struct wlan_objmgr_psoc * psoc,struct wlan_objmgr_vdev * vdev,struct ml_link_force_state * curr,struct ml_link_force_state * new,enum mlo_link_force_reason reason)1889 ml_nlink_update_force_active_num(struct wlan_objmgr_psoc *psoc, 1890 struct wlan_objmgr_vdev *vdev, 1891 struct ml_link_force_state *curr, 1892 struct ml_link_force_state *new, 1893 enum mlo_link_force_reason reason) 1894 { 1895 return QDF_STATUS_SUCCESS; 1896 } 1897 1898 static bool ml_nlink_all_links_ready_for_state_change(struct wlan_objmgr_psoc * psoc,struct wlan_objmgr_vdev * vdev,enum ml_nlink_change_event_type evt)1899 ml_nlink_all_links_ready_for_state_change(struct wlan_objmgr_psoc *psoc, 1900 struct wlan_objmgr_vdev *vdev, 1901 enum ml_nlink_change_event_type evt) 1902 { 1903 uint8_t ml_num_link = 0; 1904 uint32_t ml_link_bitmap = 0; 1905 uint8_t ml_vdev_lst[MAX_NUMBER_OF_CONC_CONNECTIONS]; 1906 qdf_freq_t ml_freq_lst[MAX_NUMBER_OF_CONC_CONNECTIONS]; 1907 uint8_t ml_linkid_lst[MAX_NUMBER_OF_CONC_CONNECTIONS]; 1908 struct ml_link_info ml_link_info[MAX_NUMBER_OF_CONC_CONNECTIONS]; 1909 1910 if (!mlo_check_if_all_links_up(vdev)) 1911 return false; 1912 1913 if (mlo_mgr_is_link_switch_in_progress(vdev) && 1914 evt != ml_nlink_connect_completion_evt) { 1915 mlo_debug("mlo vdev %d link switch in progress!", 1916 wlan_vdev_get_id(vdev)); 1917 return false; 1918 } 1919 /* For initial connecting to 2 or 3 links ML ap, assoc link and 1920 * non assoc link connected one by one, avoid changing link state 1921 * before link vdev connect completion, to check connected link count. 1922 * If < 2, means non assoc link connect is not completed, disallow 1923 * link state change. 1924 */ 1925 if (!mlo_mgr_is_link_switch_in_progress(vdev) && 1926 evt == ml_nlink_connect_completion_evt) { 1927 ml_nlink_get_link_info(psoc, vdev, NLINK_EXCLUDE_STANDBY_LINK, 1928 QDF_ARRAY_SIZE(ml_linkid_lst), 1929 ml_link_info, ml_freq_lst, ml_vdev_lst, 1930 ml_linkid_lst, &ml_num_link, 1931 &ml_link_bitmap); 1932 if (ml_num_link < 2) 1933 return false; 1934 } 1935 1936 return true; 1937 } 1938 1939 /** 1940 * ml_nlink_state_change() - Handle ML STA link force 1941 * with concurrency internal function 1942 * @psoc: PSOC object information 1943 * @reason: reason code of trigger force mode change. 1944 * @evt: event type 1945 * @data: event data 1946 * 1947 * This API handle link force for connected ML STA. 1948 * At present we only support one ML STA. so ml_nlink_get_affect_ml_sta 1949 * is invoked to get one ML STA vdev from policy mgr table. 1950 * 1951 * The flow is to get current force command which has been sent to target 1952 * and compute a new force command based on current connection table. 1953 * If any difference between "current" and "new", driver sends update 1954 * command to target. Driver will update the current force command 1955 * record after get successful respone from target. 1956 * 1957 * Return: QDF_STATUS_SUCCESS if no new command updated to target. 1958 * QDF_STATUS_E_PENDING if new command is sent to target. 1959 * otherwise QDF_STATUS error code 1960 */ ml_nlink_state_change(struct wlan_objmgr_psoc * psoc,enum mlo_link_force_reason reason,enum ml_nlink_change_event_type evt,struct ml_nlink_change_event * data)1961 static QDF_STATUS ml_nlink_state_change(struct wlan_objmgr_psoc *psoc, 1962 enum mlo_link_force_reason reason, 1963 enum ml_nlink_change_event_type evt, 1964 struct ml_nlink_change_event *data) 1965 { 1966 struct ml_link_force_state force_state = {0}; 1967 struct ml_link_force_state legacy_intf_force_state = {0}; 1968 struct ml_link_force_state curr_force_state = {0}; 1969 struct wlan_objmgr_vdev *vdev = NULL; 1970 QDF_STATUS status = QDF_STATUS_SUCCESS; 1971 1972 /* 1973 * eMLSR is allowed in MCC mode also. So, don't disable any links 1974 * if current connection happens in eMLSR mode. 1975 * eMLSR is handled by wlan_handle_emlsr_sta_concurrency 1976 */ 1977 if (policy_mgr_is_mlo_in_mode_emlsr(psoc, NULL, NULL)) { 1978 mlo_debug("Don't disable eMLSR links"); 1979 goto end; 1980 } 1981 1982 vdev = ml_nlink_get_affect_ml_sta(psoc); 1983 if (!vdev) 1984 goto end; 1985 if (!ml_nlink_all_links_ready_for_state_change(psoc, vdev, evt)) 1986 goto end; 1987 1988 ml_nlink_get_curr_force_state(psoc, vdev, &curr_force_state); 1989 1990 ml_nlink_handle_mcc_links(psoc, vdev, &force_state); 1991 1992 ml_nlink_handle_legacy_intf(psoc, vdev, &legacy_intf_force_state); 1993 1994 force_state.force_inactive_bitmap |= 1995 legacy_intf_force_state.force_inactive_bitmap; 1996 1997 if (legacy_intf_force_state.force_inactive_num && 1998 legacy_intf_force_state.force_inactive_num >= 1999 force_state.force_inactive_num) { 2000 force_state.force_inactive_num = 2001 legacy_intf_force_state.force_inactive_num; 2002 force_state.force_inactive_num_bitmap = 2003 legacy_intf_force_state.force_inactive_num_bitmap; 2004 } 2005 2006 ml_nlink_handle_dynamic_inactive(psoc, vdev, &curr_force_state, 2007 &force_state); 2008 2009 ml_nlink_update_concurrency_link_request(psoc, vdev, 2010 &force_state, 2011 reason); 2012 2013 status = ml_nlink_update_no_force_for_all(psoc, vdev, 2014 &curr_force_state, 2015 &force_state, 2016 reason); 2017 if (status == QDF_STATUS_E_PENDING || status != QDF_STATUS_SUCCESS) 2018 goto end; 2019 2020 status = ml_nlink_update_force_inactive(psoc, vdev, 2021 &curr_force_state, 2022 &force_state, 2023 reason); 2024 if (status == QDF_STATUS_E_PENDING || 2025 (status != QDF_STATUS_SUCCESS && status != QDF_STATUS_E_NOSUPPORT)) 2026 goto end; 2027 2028 status = ml_nlink_update_force_inactive_num(psoc, vdev, 2029 &curr_force_state, 2030 &force_state, 2031 reason); 2032 if (status == QDF_STATUS_E_PENDING || status != QDF_STATUS_SUCCESS) 2033 goto end; 2034 2035 /* At present, only force inactive/inactive num mode have been used 2036 * to avoid MCC, force active/active num APIs are no-op for now. 2037 */ 2038 status = ml_nlink_update_force_active(psoc, vdev, 2039 &curr_force_state, 2040 &force_state, 2041 reason); 2042 if (status == QDF_STATUS_E_PENDING || status != QDF_STATUS_SUCCESS) 2043 goto end; 2044 2045 status = ml_nlink_update_force_active_num(psoc, vdev, 2046 &curr_force_state, 2047 &force_state, 2048 reason); 2049 end: 2050 if (vdev) { 2051 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLO_MGR_ID); 2052 2053 if (status == QDF_STATUS_SUCCESS) 2054 mlo_debug("exit no force state change"); 2055 else if (status == QDF_STATUS_E_PENDING) 2056 mlo_debug("exit pending force state change"); 2057 else 2058 mlo_err("exit err %d state change", status); 2059 } 2060 2061 return status; 2062 } 2063 2064 /** 2065 * ml_nlink_state_change_handler() - Handle ML STA link force 2066 * with concurrency 2067 * @psoc: PSOC object information 2068 * @vdev: ml sta vdev object 2069 * @reason: reason code of trigger force mode change. 2070 * @evt: event type 2071 * @data: event data 2072 * 2073 * Return: QDF_STATUS_SUCCESS if successfully 2074 */ 2075 static QDF_STATUS ml_nlink_state_change_handler(struct wlan_objmgr_psoc * psoc,struct wlan_objmgr_vdev * vdev,enum mlo_link_force_reason reason,enum ml_nlink_change_event_type evt,struct ml_nlink_change_event * data)2076 ml_nlink_state_change_handler(struct wlan_objmgr_psoc *psoc, 2077 struct wlan_objmgr_vdev *vdev, 2078 enum mlo_link_force_reason reason, 2079 enum ml_nlink_change_event_type evt, 2080 struct ml_nlink_change_event *data) 2081 { 2082 enum QDF_OPMODE mode = wlan_vdev_mlme_get_opmode(vdev); 2083 uint8_t vdev_id = wlan_vdev_get_id(vdev); 2084 QDF_STATUS status = QDF_STATUS_SUCCESS; 2085 2086 /* If WMI_SERVICE_N_LINK_MLO_SUPPORT = 381 is enabled, 2087 * indicate FW support N MLO link & vdev re-purpose between links, 2088 * host will use linkid bitmap to force inactive/active links 2089 * by API ml_nlink_state_change. 2090 * Otherwise, use legacy policy mgr API to inactive/active based 2091 * on vdev id bitmap. 2092 */ 2093 if (ml_is_nlink_service_supported(psoc)) 2094 status = ml_nlink_state_change(psoc, reason, evt, data); 2095 else if (reason == MLO_LINK_FORCE_REASON_CONNECT) 2096 policy_mgr_handle_ml_sta_links_on_vdev_up_csa(psoc, mode, 2097 vdev_id); 2098 else 2099 policy_mgr_handle_ml_sta_links_on_vdev_down(psoc, mode, 2100 vdev_id); 2101 2102 return status; 2103 } 2104 2105 static QDF_STATUS ml_nlink_tdls_event_handler(struct wlan_objmgr_psoc * psoc,struct wlan_objmgr_vdev * vdev,enum ml_nlink_change_event_type evt,struct ml_nlink_change_event * data)2106 ml_nlink_tdls_event_handler(struct wlan_objmgr_psoc *psoc, 2107 struct wlan_objmgr_vdev *vdev, 2108 enum ml_nlink_change_event_type evt, 2109 struct ml_nlink_change_event *data) 2110 { 2111 struct ml_link_force_state curr_force_state = {0}; 2112 QDF_STATUS status; 2113 struct set_link_req vendor_req = {0}; 2114 2115 ml_nlink_get_curr_force_state(psoc, vdev, &curr_force_state); 2116 2117 switch (data->evt.tdls.mode) { 2118 case MLO_LINK_FORCE_MODE_ACTIVE: 2119 if ((data->evt.tdls.link_bitmap & 2120 curr_force_state.force_active_bitmap) == 2121 data->evt.tdls.link_bitmap) { 2122 mlo_debug("link_bitmap 0x%x already active, 0x%x", 2123 data->evt.tdls.link_bitmap, 2124 curr_force_state.force_active_bitmap); 2125 return QDF_STATUS_SUCCESS; 2126 } 2127 if (data->evt.tdls.link_bitmap & 2128 (curr_force_state.force_inactive_bitmap | 2129 curr_force_state.curr_dynamic_inactive_bitmap)) { 2130 mlo_debug("link_bitmap 0x%x can't be active due to concurrency, 0x%x 0x%x", 2131 data->evt.tdls.link_bitmap, 2132 curr_force_state.force_inactive_bitmap, 2133 curr_force_state. 2134 curr_dynamic_inactive_bitmap); 2135 return QDF_STATUS_E_INVAL; 2136 } 2137 break; 2138 case MLO_LINK_FORCE_MODE_NO_FORCE: 2139 if (data->evt.tdls.link_bitmap & 2140 curr_force_state.force_inactive_bitmap) { 2141 mlo_debug("link_bitmap 0x%x can't be no_force due to concurrency, 0x%x", 2142 data->evt.tdls.link_bitmap, 2143 curr_force_state.force_inactive_bitmap); 2144 return QDF_STATUS_E_INVAL; 2145 } 2146 if (!(data->evt.tdls.link_bitmap & 2147 curr_force_state.force_active_bitmap)) { 2148 mlo_debug("link_bitmap 0x%x already no force, 0x%x", 2149 data->evt.tdls.link_bitmap, 2150 curr_force_state.force_active_bitmap); 2151 return QDF_STATUS_SUCCESS; 2152 } 2153 ml_nlink_get_force_link_request(psoc, vdev, &vendor_req, 2154 SET_LINK_FROM_VENDOR_CMD); 2155 if (data->evt.tdls.link_bitmap & 2156 vendor_req.force_active_bitmap) { 2157 mlo_debug("link_bitmap 0x%x active hold by vendor cmd, 0x%x", 2158 data->evt.tdls.link_bitmap, 2159 vendor_req.force_active_bitmap); 2160 return QDF_STATUS_SUCCESS; 2161 } 2162 break; 2163 default: 2164 mlo_err("unhandled for tdls force mode %d", 2165 data->evt.tdls.mode); 2166 return QDF_STATUS_E_INVAL; 2167 } 2168 2169 if (ml_is_nlink_service_supported(psoc)) 2170 status = policy_mgr_mlo_sta_set_nlink( 2171 psoc, wlan_vdev_get_id(vdev), 2172 data->evt.tdls.reason, 2173 data->evt.tdls.mode, 2174 0, 2175 data->evt.tdls.link_bitmap, 2176 0, 2177 0); 2178 else 2179 status = 2180 policy_mgr_mlo_sta_set_link(psoc, 2181 data->evt.tdls.reason, 2182 data->evt.tdls.mode, 2183 data->evt.tdls.vdev_count, 2184 data->evt.tdls.mlo_vdev_lst); 2185 2186 return status; 2187 } 2188 2189 static QDF_STATUS ml_nlink_vendor_cmd_handler(struct wlan_objmgr_psoc * psoc,struct wlan_objmgr_vdev * vdev,enum ml_nlink_change_event_type evt,struct ml_nlink_change_event * data)2190 ml_nlink_vendor_cmd_handler(struct wlan_objmgr_psoc *psoc, 2191 struct wlan_objmgr_vdev *vdev, 2192 enum ml_nlink_change_event_type evt, 2193 struct ml_nlink_change_event *data) 2194 { 2195 struct set_link_req req = {0}; 2196 QDF_STATUS status = QDF_STATUS_SUCCESS; 2197 2198 mlo_debug("link ctrl %d mode %d reason %d num %d 0x%x 0x%x", 2199 data->evt.vendor.link_ctrl_mode, 2200 data->evt.vendor.mode, 2201 data->evt.vendor.reason, 2202 data->evt.vendor.link_num, 2203 data->evt.vendor.link_bitmap, 2204 data->evt.vendor.link_bitmap2); 2205 switch (data->evt.vendor.link_ctrl_mode) { 2206 case LINK_CONTROL_MODE_DEFAULT: 2207 ml_nlink_clr_force_link_request(psoc, vdev, 2208 SET_LINK_FROM_VENDOR_CMD); 2209 break; 2210 case LINK_CONTROL_MODE_USER: 2211 req.mode = data->evt.vendor.mode; 2212 req.reason = data->evt.vendor.reason; 2213 req.force_active_bitmap = data->evt.vendor.link_bitmap; 2214 req.force_inactive_bitmap = data->evt.vendor.link_bitmap2; 2215 ml_nlink_update_force_link_request(psoc, vdev, &req, 2216 SET_LINK_FROM_VENDOR_CMD); 2217 break; 2218 case LINK_CONTROL_MODE_MIXED: 2219 req.mode = data->evt.vendor.mode; 2220 req.reason = data->evt.vendor.reason; 2221 req.force_active_num = data->evt.vendor.link_num; 2222 req.force_active_num_bitmap = data->evt.vendor.link_bitmap; 2223 ml_nlink_update_force_link_request(psoc, vdev, &req, 2224 SET_LINK_FROM_VENDOR_CMD); 2225 break; 2226 default: 2227 status = QDF_STATUS_E_INVAL; 2228 } 2229 2230 return status; 2231 } 2232 2233 static QDF_STATUS ml_nlink_swtich_dynamic_inactive_link(struct wlan_objmgr_psoc * psoc,struct wlan_objmgr_vdev * vdev)2234 ml_nlink_swtich_dynamic_inactive_link(struct wlan_objmgr_psoc *psoc, 2235 struct wlan_objmgr_vdev *vdev) 2236 { 2237 uint8_t link_id; 2238 uint32_t standby_link_bitmap, dynamic_inactive_bitmap; 2239 struct ml_link_force_state curr_force_state = {0}; 2240 uint8_t link_ids[MAX_MLO_LINK_ID]; 2241 uint8_t num_ids; 2242 2243 link_id = wlan_vdev_get_link_id(vdev); 2244 if (link_id >= MAX_MLO_LINK_ID) { 2245 mlo_err("invalid link id %d", link_id); 2246 return QDF_STATUS_E_INVAL; 2247 } 2248 2249 ml_nlink_get_curr_force_state(psoc, vdev, &curr_force_state); 2250 standby_link_bitmap = ml_nlink_get_standby_link_bitmap(psoc, vdev); 2251 standby_link_bitmap &= curr_force_state.force_inactive_num_bitmap & 2252 ~(1 << link_id); 2253 /* In DBS RD, ML STA 2+5+6(standby link), force inactive num = 1 and 2254 * force inactive bitmap with 5 + 6 links will be sent to FW, host 2255 * will select 6G as dynamic inactive link, 5G vdev will be kept in 2256 * policy mgr active connection table. 2257 * If FW link switch and repurpose 5G vdev to 6G, host will need to 2258 * select 5G standby link as dynamic inactive. 2259 * Then 6G vdev can be moved to policy mgr active connection table. 2260 */ 2261 if (((1 << link_id) & curr_force_state.curr_dynamic_inactive_bitmap) && 2262 ((1 << link_id) & curr_force_state.force_inactive_num_bitmap) && 2263 !(standby_link_bitmap & 2264 curr_force_state.curr_dynamic_inactive_bitmap) && 2265 (standby_link_bitmap & 2266 curr_force_state.force_inactive_num_bitmap)) { 2267 num_ids = convert_link_bitmap_to_link_ids( 2268 standby_link_bitmap, 2269 QDF_ARRAY_SIZE(link_ids), 2270 link_ids); 2271 if (!num_ids) { 2272 mlo_err("unexpected 0 link ids for bitmap 0x%x", 2273 standby_link_bitmap); 2274 return QDF_STATUS_E_INVAL; 2275 } 2276 /* Remove the link from dynamic inactive bitmap, 2277 * add the standby link to dynamic inactive bitmap. 2278 */ 2279 dynamic_inactive_bitmap = 2280 curr_force_state.curr_dynamic_inactive_bitmap & 2281 ~(1 << link_id); 2282 dynamic_inactive_bitmap |= 1 << link_ids[0]; 2283 mlo_debug("move out vdev %d link id %d from dynamic inactive, add standby link id %d", 2284 wlan_vdev_get_id(vdev), link_id, link_ids[0]); 2285 ml_nlink_set_dynamic_inactive_links(psoc, vdev, 2286 dynamic_inactive_bitmap); 2287 } 2288 2289 return QDF_STATUS_SUCCESS; 2290 } 2291 2292 QDF_STATUS ml_nlink_conn_change_notify(struct wlan_objmgr_psoc * psoc,uint8_t vdev_id,enum ml_nlink_change_event_type evt,struct ml_nlink_change_event * data)2293 ml_nlink_conn_change_notify(struct wlan_objmgr_psoc *psoc, 2294 uint8_t vdev_id, 2295 enum ml_nlink_change_event_type evt, 2296 struct ml_nlink_change_event *data) 2297 { 2298 struct wlan_objmgr_vdev *vdev; 2299 enum QDF_OPMODE mode; 2300 QDF_STATUS status = QDF_STATUS_SUCCESS; 2301 struct ml_link_force_state curr_force_state = {0}; 2302 bool is_set_link_in_progress = policy_mgr_is_set_link_in_progress(psoc); 2303 bool is_host_force; 2304 2305 mlo_debug("vdev %d %s(%d)", vdev_id, link_evt_to_string(evt), 2306 evt); 2307 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id, 2308 WLAN_MLO_MGR_ID); 2309 if (!vdev) { 2310 mlo_err("invalid vdev id %d ", vdev_id); 2311 return QDF_STATUS_E_INVAL; 2312 } 2313 mode = wlan_vdev_mlme_get_opmode(vdev); 2314 2315 switch (evt) { 2316 case ml_nlink_link_switch_start_evt: 2317 if (data->evt.link_switch.reason == 2318 MLO_LINK_SWITCH_REASON_HOST_FORCE) { 2319 is_host_force = true; 2320 } else { 2321 is_host_force = false; 2322 } 2323 2324 mlo_debug("set_link_in_prog %d reason %d", 2325 is_set_link_in_progress, 2326 data->evt.link_switch.reason); 2327 2328 if (is_set_link_in_progress) { 2329 /* If set active is in progress then only accept host 2330 * force link switch requests from FW 2331 */ 2332 if (is_host_force) 2333 status = QDF_STATUS_SUCCESS; 2334 else 2335 status = QDF_STATUS_E_INVAL; 2336 break; 2337 } else if (is_host_force) { 2338 /* If set active is not in progress but FW sent host 2339 * force then reject the link switch 2340 */ 2341 status = QDF_STATUS_E_INVAL; 2342 break; 2343 } 2344 2345 ml_nlink_get_curr_force_state(psoc, vdev, &curr_force_state); 2346 if ((1 << data->evt.link_switch.new_ieee_link_id) & 2347 curr_force_state.force_inactive_bitmap) { 2348 mlo_debug("target link %d is force inactive, don't switch to it", 2349 data->evt.link_switch.new_ieee_link_id); 2350 status = QDF_STATUS_E_INVAL; 2351 } 2352 break; 2353 case ml_nlink_link_switch_pre_completion_evt: 2354 status = ml_nlink_swtich_dynamic_inactive_link( 2355 psoc, vdev); 2356 break; 2357 case ml_nlink_roam_sync_start_evt: 2358 ml_nlink_clr_force_state(psoc, vdev); 2359 break; 2360 case ml_nlink_roam_sync_completion_evt: 2361 status = ml_nlink_state_change_handler( 2362 psoc, vdev, MLO_LINK_FORCE_REASON_CONNECT, 2363 evt, data); 2364 break; 2365 case ml_nlink_connect_start_evt: 2366 ml_nlink_clr_force_state(psoc, vdev); 2367 break; 2368 case ml_nlink_connect_completion_evt: 2369 status = ml_nlink_state_change_handler( 2370 psoc, vdev, MLO_LINK_FORCE_REASON_CONNECT, 2371 evt, data); 2372 break; 2373 case ml_nlink_disconnect_start_evt: 2374 ml_nlink_clr_force_state(psoc, vdev); 2375 break; 2376 case ml_nlink_disconnect_completion_evt: 2377 status = ml_nlink_state_change_handler( 2378 psoc, vdev, MLO_LINK_FORCE_REASON_DISCONNECT, 2379 evt, data); 2380 break; 2381 case ml_nlink_ap_started_evt: 2382 status = ml_nlink_state_change_handler( 2383 psoc, vdev, MLO_LINK_FORCE_REASON_CONNECT, 2384 evt, data); 2385 break; 2386 case ml_nlink_ap_stopped_evt: 2387 status = ml_nlink_state_change_handler( 2388 psoc, vdev, MLO_LINK_FORCE_REASON_DISCONNECT, 2389 evt, data); 2390 break; 2391 case ml_nlink_connection_updated_evt: 2392 if (mode == QDF_STA_MODE && 2393 (MLME_IS_ROAM_SYNCH_IN_PROGRESS(psoc, vdev_id) || 2394 MLME_IS_MLO_ROAM_SYNCH_IN_PROGRESS(psoc, vdev_id))) { 2395 mlo_debug("vdev id %d in roam sync", vdev_id); 2396 break; 2397 } 2398 status = ml_nlink_state_change_handler( 2399 psoc, vdev, MLO_LINK_FORCE_REASON_CONNECT, 2400 evt, data); 2401 break; 2402 case ml_nlink_tdls_request_evt: 2403 status = ml_nlink_tdls_event_handler( 2404 psoc, vdev, evt, data); 2405 break; 2406 case ml_nlink_vendor_cmd_request_evt: 2407 status = ml_nlink_vendor_cmd_handler( 2408 psoc, vdev, evt, data); 2409 break; 2410 default: 2411 break; 2412 } 2413 2414 if (vdev) 2415 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLO_MGR_ID); 2416 2417 return status; 2418 } 2419 2420 void ml_nlink_vendor_command_set_link(struct wlan_objmgr_psoc * psoc,uint8_t vdev_id,enum link_control_modes link_control_mode,enum mlo_link_force_reason reason,enum mlo_link_force_mode mode,uint8_t link_num,uint16_t link_bitmap,uint16_t link_bitmap2)2421 ml_nlink_vendor_command_set_link(struct wlan_objmgr_psoc *psoc, 2422 uint8_t vdev_id, 2423 enum link_control_modes link_control_mode, 2424 enum mlo_link_force_reason reason, 2425 enum mlo_link_force_mode mode, 2426 uint8_t link_num, 2427 uint16_t link_bitmap, 2428 uint16_t link_bitmap2) 2429 { 2430 struct ml_nlink_change_event data; 2431 2432 qdf_mem_zero(&data, sizeof(data)); 2433 data.evt.vendor.link_ctrl_mode = link_control_mode; 2434 data.evt.vendor.mode = mode; 2435 data.evt.vendor.reason = reason; 2436 data.evt.vendor.link_num = link_num; 2437 data.evt.vendor.link_bitmap = link_bitmap; 2438 data.evt.vendor.link_bitmap2 = link_bitmap2; 2439 2440 ml_nlink_conn_change_notify( 2441 psoc, vdev_id, 2442 ml_nlink_vendor_cmd_request_evt, &data); 2443 } 2444