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