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