xref: /wlan-driver/qcacld-3.0/components/umac/mlme/mlo_mgr/src/wlan_mlo_link_force.c (revision 5113495b16420b49004c444715d2daae2066e7dc)
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