1 /*
2  * Copyright (c) 2021, The Linux Foundation. All rights reserved.
3  * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
4  *
5  * Permission to use, copy, modify, and/or distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17 
18 #include "wlan_mlo_mgr_main.h"
19 #include "qdf_types.h"
20 #include "wlan_cmn.h"
21 #include "wlan_mlo_mgr_peer.h"
22 #include <wlan_mlo_mgr_ap.h>
23 #include <wlan_mlo_mgr_setup.h>
24 #include <wlan_utility.h>
25 #include <wlan_reg_services_api.h>
26 #include <wlan_mlo_mgr_sta.h>
27 #include <wlan_objmgr_vdev_obj.h>
28 #include <wlan_mgmt_txrx_rx_reo_utils_api.h>
29 /**
30  * struct mlpeer_data: PSOC peers MLO data
31  * @total_rssi:  sum of RSSI of all ML peers
32  * @num_ml_peers: Number of ML peer's with this PSOC as TQM
33  * @max_ml_peers: Max ML peers can have this PSOC as TQM
34  *                (it is to distribute peers across all PSOCs)
35  * @num_non_ml_peers: Non MLO peers of this PSOC
36  */
37 struct mlpeer_data {
38 	int32_t total_rssi;
39 	uint16_t num_ml_peers;
40 	uint16_t max_ml_peers;
41 	uint16_t num_non_ml_peers;
42 };
43 
44 /**
45  * struct mlo_all_link_rssi: structure to collect TQM params for all PSOCs
46  * @psoc_tqm_parms:  It collects peer data for all PSOCs
47  * @num_psocs:       Number of PSOCs in the system
48  * @current_psoc_id: current psoc id, it is for iterator
49  */
50 struct mlo_all_link_rssi {
51 	struct mlpeer_data psoc_tqm_parms[WLAN_OBJMGR_MAX_DEVICES];
52 	uint8_t num_psocs;
53 	uint8_t current_psoc_id;
54 };
55 
56 /* Invalid TQM/PSOC ID */
57 #define ML_INVALID_PRIMARY_TQM   0xff
58 /* Congestion value */
59 #define ML_PRIMARY_TQM_CONGESTION 30
60 /* PTQM migration timeout value in ms */
61 #define ML_PRIMARY_TQM_MIGRATRION_TIMEOUT 4000
62 /* Link ID used for WDS Bridge*/
63 #define WDS_BRIDGE_VDEV_LINK_ID (WLAN_LINK_ID_INVALID - 1)
64 
wlan_mlo_peer_get_rssi(struct wlan_objmgr_psoc * psoc,void * obj,void * args)65 static void wlan_mlo_peer_get_rssi(struct wlan_objmgr_psoc *psoc,
66 				   void *obj, void *args)
67 {
68 	struct wlan_mlo_peer_context *mlo_peer_ctx;
69 	struct wlan_objmgr_peer *peer = (struct wlan_objmgr_peer *)obj;
70 	struct mlo_all_link_rssi *rssi_data = (struct mlo_all_link_rssi *)args;
71 	struct mlpeer_data *tqm_params = NULL;
72 	uint8_t index;
73 
74 	mlo_peer_ctx = peer->mlo_peer_ctx;
75 	index = rssi_data->current_psoc_id;
76 	tqm_params = &rssi_data->psoc_tqm_parms[index];
77 
78 	if (!wlan_peer_is_mlo(peer) && !mlo_peer_ctx) {
79 		if (wlan_peer_get_peer_type(peer) == WLAN_PEER_STA)
80 			tqm_params->num_non_ml_peers += 1;
81 		return;
82 	}
83 
84 	if (!mlo_peer_ctx)
85 		return;
86 
87 	/* If this psoc is new primary UMAC after migration,
88 	 * account RSSI on new link
89 	 */
90 	if (mlo_peer_ctx->migrate_primary_umac_psoc_id ==
91 			rssi_data->current_psoc_id) {
92 		tqm_params->total_rssi += mlo_peer_ctx->avg_link_rssi;
93 		tqm_params->num_ml_peers += 1;
94 		return;
95 	}
96 
97 	/* If this psoc is not primary UMAC or if TQM migration is happening
98 	 * from current primary psoc, don't account RSSI
99 	 */
100 	if (mlo_peer_ctx->primary_umac_psoc_id == rssi_data->current_psoc_id &&
101 	    mlo_peer_ctx->migrate_primary_umac_psoc_id ==
102 	    ML_INVALID_PRIMARY_TQM) {
103 		tqm_params->total_rssi += mlo_peer_ctx->avg_link_rssi;
104 		tqm_params->num_ml_peers += 1;
105 	}
106 }
107 
wlan_get_rssi_data_each_psoc(struct wlan_objmgr_psoc * psoc,void * arg,uint8_t index)108 static void wlan_get_rssi_data_each_psoc(struct wlan_objmgr_psoc *psoc,
109 					 void *arg, uint8_t index)
110 {
111 	struct mlo_all_link_rssi *rssi_data = (struct mlo_all_link_rssi *)arg;
112 	struct mlpeer_data *tqm_params = NULL;
113 
114 	tqm_params = &rssi_data->psoc_tqm_parms[index];
115 
116 	tqm_params->total_rssi = 0;
117 	tqm_params->num_ml_peers = 0;
118 	tqm_params->num_non_ml_peers = 0;
119 	tqm_params->max_ml_peers = MAX_MLO_PEER;
120 
121 	rssi_data->current_psoc_id = index;
122 	rssi_data->num_psocs++;
123 
124 	wlan_objmgr_iterate_obj_list(psoc, WLAN_PEER_OP,
125 				     wlan_mlo_peer_get_rssi, rssi_data, 0,
126 				     WLAN_MLO_MGR_ID);
127 }
128 
mld_get_link_rssi(struct mlo_all_link_rssi * rssi_data)129 static QDF_STATUS mld_get_link_rssi(struct mlo_all_link_rssi *rssi_data)
130 {
131 	rssi_data->num_psocs = 0;
132 
133 	wlan_objmgr_iterate_psoc_list(wlan_get_rssi_data_each_psoc,
134 				      rssi_data, WLAN_MLO_MGR_ID);
135 
136 	return QDF_STATUS_SUCCESS;
137 }
138 
139 uint8_t
wlan_mld_get_best_primary_umac_w_rssi(struct wlan_mlo_peer_context * ml_peer,struct wlan_objmgr_vdev * link_vdevs[],bool allow_all_links)140 wlan_mld_get_best_primary_umac_w_rssi(struct wlan_mlo_peer_context *ml_peer,
141 				      struct wlan_objmgr_vdev *link_vdevs[],
142 				      bool allow_all_links)
143 {
144 	struct mlo_all_link_rssi rssi_data;
145 	uint8_t i;
146 	int32_t avg_rssi[WLAN_OBJMGR_MAX_DEVICES] = {0};
147 	int32_t diff_rssi[WLAN_OBJMGR_MAX_DEVICES] = {0};
148 	int32_t diff_low;
149 	bool mld_sta_links[WLAN_OBJMGR_MAX_DEVICES] = {0};
150 	bool mld_no_sta[WLAN_OBJMGR_MAX_DEVICES] = {0};
151 	uint8_t prim_link, id, prim_link_hi;
152 	uint8_t num_psocs;
153 	struct mlpeer_data *tqm_params = NULL;
154 	struct wlan_channel *channel;
155 	enum phy_ch_width sec_hi_bw, hi_bw;
156 	uint8_t cong = ML_PRIMARY_TQM_CONGESTION;
157 	uint16_t mld_ml_sta_count[WLAN_OBJMGR_MAX_DEVICES] = {0};
158 	enum phy_ch_width mld_ch_width[WLAN_OBJMGR_MAX_DEVICES];
159 	uint8_t psoc_w_nosta;
160 	uint16_t ml_sta_count = 0;
161 	uint32_t total_cap, cap;
162 	uint16_t bw;
163 	bool group_full[WLAN_OBJMGR_MAX_DEVICES] = {0};
164 	uint16_t group_size[WLAN_OBJMGR_MAX_DEVICES] = {0};
165 	uint16_t grp_size = 0;
166 	uint16_t group_full_count = 0;
167 
168 	mld_get_link_rssi(&rssi_data);
169 
170 	for (i = 0; i < rssi_data.num_psocs; i++) {
171 		tqm_params = &rssi_data.psoc_tqm_parms[i];
172 
173 		if (tqm_params->num_ml_peers)
174 			avg_rssi[i] = (tqm_params->total_rssi /
175 				       tqm_params->num_ml_peers);
176 	}
177 
178 	/**
179 	 * If MLD STA associated to a set of links, choose primary UMAC
180 	 * from those links only
181 	 */
182 	num_psocs = 0;
183 	psoc_w_nosta = 0;
184 	for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++)
185 		mld_ch_width[i] = CH_WIDTH_INVALID;
186 
187 	for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
188 		if (!link_vdevs[i])
189 			continue;
190 
191 		id = wlan_vdev_get_psoc_id(link_vdevs[i]);
192 		if (id >= WLAN_OBJMGR_MAX_DEVICES)
193 			continue;
194 
195 		if (!allow_all_links && wlan_vdev_skip_pumac(link_vdevs[i])) {
196 			mlo_err("Skip Radio for Primary MLO umac");
197 			mld_sta_links[id] = false;
198 			continue;
199 		}
200 
201 		tqm_params = &rssi_data.psoc_tqm_parms[id];
202 		mld_sta_links[id] = true;
203 
204 		channel = wlan_vdev_mlme_get_bss_chan(link_vdevs[i]);
205 		mld_ch_width[id] = channel->ch_width;
206 
207 		if ((tqm_params->num_ml_peers +
208 		     tqm_params->num_non_ml_peers) == 0) {
209 			/* If this PSOC has no stations */
210 			mld_no_sta[id] = true;
211 			psoc_w_nosta++;
212 		}
213 
214 		mld_ml_sta_count[id] = tqm_params->num_ml_peers;
215 		/* Update total MLO STA count */
216 		ml_sta_count += tqm_params->num_ml_peers;
217 
218 		num_psocs++;
219 
220 		/* If no stations are associated, derive diff rssi
221 		 * based on psoc id {0-20, 20-40, 40 } so that
222 		 * stations are distributed across TQMs
223 		 */
224 		if (!avg_rssi[id]) {
225 			diff_rssi[id] = (id * 20);
226 			continue;
227 		}
228 		diff_rssi[id] = (ml_peer->avg_link_rssi >= avg_rssi[id]) ?
229 				(ml_peer->avg_link_rssi - avg_rssi[id]) :
230 				(avg_rssi[id] - ml_peer->avg_link_rssi);
231 
232 	}
233 
234 	prim_link = ML_INVALID_PRIMARY_TQM;
235 
236 	/* If one of the PSOCs doesn't have any station select that PSOC as
237 	 * primary TQM. If more than one PSOC have no stations as Primary TQM
238 	 * the vdev with less bw needs to be selected as Primary TQM
239 	 */
240 	if (psoc_w_nosta == 1) {
241 		for (i = 0; i < WLAN_OBJMGR_MAX_DEVICES; i++) {
242 			if (mld_no_sta[i]) {
243 				prim_link = i;
244 				break;
245 			}
246 		}
247 	} else if (psoc_w_nosta > 1) {
248 		hi_bw = CH_WIDTH_INVALID;
249 		sec_hi_bw = CH_WIDTH_INVALID;
250 		for (i = 0; i < WLAN_OBJMGR_MAX_DEVICES; i++) {
251 			if (!mld_no_sta[i])
252 				continue;
253 
254 			if (hi_bw == CH_WIDTH_INVALID) {
255 				prim_link_hi = i;
256 				hi_bw = mld_ch_width[i];
257 				continue;
258 			}
259 			/* if bw is 320MHZ mark it as highest ch width */
260 			if (mld_ch_width[i] == CH_WIDTH_320MHZ) {
261 				prim_link = prim_link_hi;
262 				sec_hi_bw = hi_bw;
263 				hi_bw = mld_ch_width[i];
264 				prim_link_hi = i;
265 			}
266 			/* If bw is less than or equal to 160 MHZ
267 			 * and chwidth is greater than than other link
268 			 * Mark this link as primary link
269 			 */
270 			if (mld_ch_width[i] <= CH_WIDTH_160MHZ) {
271 				if (hi_bw < mld_ch_width[i]) {
272 					/* move high bw to second high bw */
273 					prim_link = prim_link_hi;
274 					sec_hi_bw = hi_bw;
275 
276 					hi_bw = mld_ch_width[i];
277 					prim_link_hi = i;
278 				} else if ((sec_hi_bw == CH_WIDTH_INVALID) ||
279 					   (sec_hi_bw < mld_ch_width[i])) {
280 					/* update sec high bw */
281 					sec_hi_bw = mld_ch_width[i];
282 					prim_link = i;
283 				}
284 			}
285 		}
286 	} else {
287 		total_cap = 0;
288 		for (i = 0; i < WLAN_OBJMGR_MAX_DEVICES; i++) {
289 			bw = wlan_reg_get_bw_value(mld_ch_width[i]);
290 			total_cap += bw * (100 - cong);
291 		}
292 
293 		group_full_count = 0;
294 		for (i = 0; i < WLAN_OBJMGR_MAX_DEVICES; i++) {
295 			if (!mld_sta_links[i])
296 				continue;
297 
298 			bw = wlan_reg_get_bw_value(mld_ch_width[i]);
299 			cap = bw * (100 - cong);
300 			grp_size = (ml_sta_count) * ((cap * 100) / total_cap);
301 			group_size[i] = grp_size / 100;
302 			if (group_size[i] <=  mld_ml_sta_count[i]) {
303 				group_full[i] = true;
304 				group_full_count++;
305 			}
306 		}
307 
308 		if ((num_psocs - group_full_count) == 1) {
309 			for (i = 0; i < WLAN_OBJMGR_MAX_DEVICES; i++) {
310 				if (!mld_sta_links[i])
311 					continue;
312 
313 				if (group_full[i])
314 					continue;
315 
316 				prim_link = i;
317 				break;
318 			}
319 		} else {
320 			diff_low = 0;
321 			/* find min diff, based on it, allocate primary umac */
322 			for (i = 0; i < WLAN_OBJMGR_MAX_DEVICES; i++) {
323 				if (!mld_sta_links[i])
324 					continue;
325 
326 				/* First iteration */
327 				if (diff_low == 0) {
328 					diff_low = diff_rssi[i];
329 					prim_link = i;
330 				} else if (diff_low > diff_rssi[i]) {
331 					diff_low = diff_rssi[i];
332 					prim_link = i;
333 				}
334 			}
335 		}
336 	}
337 
338 	if (prim_link != ML_INVALID_PRIMARY_TQM)
339 		return prim_link;
340 
341 	/* If primary link id is not found, return id of 1st available link */
342 	for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
343 		if (!link_vdevs[i])
344 			continue;
345 
346 		if (!allow_all_links && wlan_vdev_skip_pumac(link_vdevs[i])) {
347 			mlo_debug("Skip Radio for Primary MLO umac");
348 			continue;
349 		}
350 		id = wlan_vdev_get_psoc_id(link_vdevs[i]);
351 		if (id >= WLAN_OBJMGR_MAX_DEVICES)
352 			continue;
353 
354 		return wlan_vdev_get_psoc_id(link_vdevs[i]);
355 	}
356 
357 	return ML_INVALID_PRIMARY_TQM;
358 }
359 
mlo_peer_assign_primary_umac(struct wlan_mlo_peer_context * ml_peer,struct wlan_mlo_link_peer_entry * peer_entry)360 void mlo_peer_assign_primary_umac(
361 		struct wlan_mlo_peer_context *ml_peer,
362 		struct wlan_mlo_link_peer_entry *peer_entry)
363 {
364 	struct wlan_mlo_link_peer_entry *peer_ent_iter;
365 	uint8_t i;
366 	uint8_t primary_umac_set = 0;
367 	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
368 #if defined(WLAN_FEATURE_11BE_MLO) && defined(WLAN_MLO_MULTI_CHIP)
369 	bool is_central_primary = false;
370 	uint8_t bridge_umac_id = -1;
371 	uint8_t link_peer_psoc_id;
372 	struct wlan_mlo_dev_context *ml_dev = NULL;
373 #endif
374 
375 	/* If MLD is within single SOC, then assoc link becomes
376 	 * primary umac
377 	 */
378 	if (ml_peer->primary_umac_psoc_id == ML_PRIMARY_UMAC_ID_INVAL) {
379 #if defined(WLAN_FEATURE_11BE_MLO) && defined(WLAN_MLO_MULTI_CHIP)
380 		ml_dev = ml_peer->ml_dev;
381 
382 		if (!ml_dev) {
383 			mlo_err("ML dev ctx is NULL");
384 			return;
385 		}
386 		if (ml_dev->bridge_sta_ctx) {
387 			is_central_primary = ml_dev->bridge_sta_ctx->is_force_central_primary;
388 			bridge_umac_id = ml_dev->bridge_sta_ctx->bridge_umac_id;
389 		}
390 		link_peer_psoc_id = wlan_peer_get_psoc_id(peer_entry->link_peer);
391 		if (is_central_primary) {
392 			if (link_peer_psoc_id == bridge_umac_id) {
393 				peer_entry->is_primary = true;
394 				ml_peer->primary_umac_psoc_id = bridge_umac_id;
395 			} else {
396 				peer_entry->is_primary = false;
397 				ml_peer->primary_umac_psoc_id = bridge_umac_id;
398 			}
399 
400 		} else {
401 
402 #endif
403 			if (wlan_peer_mlme_is_assoc_peer(peer_entry->link_peer)) {
404 				peer_entry->is_primary = true;
405 				ml_peer->primary_umac_psoc_id =
406 					wlan_peer_get_psoc_id(peer_entry->link_peer);
407 			} else {
408 				peer_entry->is_primary = false;
409 			}
410 
411 #if defined(WLAN_FEATURE_11BE_MLO) && defined(WLAN_MLO_MULTI_CHIP)
412 		}
413 #endif
414 	} else {
415 		if ((wlan_peer_mlme_is_assoc_peer(peer_entry->link_peer)) &&
416 		    (ml_peer->max_links > 1) &&
417 		    (mlo_ctx->force_non_assoc_prim_umac)) {
418 			peer_entry->is_primary = false;
419 			return;
420 		}
421 
422 		/* If this peer PSOC is not derived as Primary PSOC,
423 		 * mark is_primary as false
424 		 */
425 		if (wlan_peer_get_psoc_id(peer_entry->link_peer) !=
426 				ml_peer->primary_umac_psoc_id) {
427 			peer_entry->is_primary = false;
428 			return;
429 		}
430 
431 		/* For single SOC, check whether is_primary is set for
432 		 * other partner peer, then mark is_primary false for this peer
433 		 */
434 		for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
435 			peer_ent_iter = &ml_peer->peer_list[i];
436 
437 			if (!peer_ent_iter->link_peer)
438 				continue;
439 
440 			/* Check for other link peers */
441 			if (peer_ent_iter == peer_entry)
442 				continue;
443 
444 			if (wlan_peer_get_psoc_id(peer_ent_iter->link_peer) !=
445 					ml_peer->primary_umac_psoc_id)
446 				continue;
447 
448 			if (peer_ent_iter->is_primary)
449 				primary_umac_set = 1;
450 		}
451 
452 		if (primary_umac_set)
453 			peer_entry->is_primary = false;
454 		else
455 			peer_entry->is_primary = true;
456 	}
457 }
458 
wlan_vdev_derive_link_rssi(struct wlan_objmgr_vdev * vdev,struct wlan_objmgr_vdev * assoc_vdev,int8_t rssi)459 static int8_t wlan_vdev_derive_link_rssi(struct wlan_objmgr_vdev *vdev,
460 					 struct wlan_objmgr_vdev *assoc_vdev,
461 					 int8_t rssi)
462 {
463 	struct wlan_channel *channel, *assoc_channel;
464 	uint16_t ch_freq, assoc_freq;
465 	uint8_t tx_pow, assoc_tx_pow;
466 	int8_t diff_txpow;
467 	struct wlan_objmgr_pdev *pdev, *assoc_pdev;
468 	uint8_t log10_freq;
469 	uint8_t derived_rssi;
470 	int16_t ten_derived_rssi;
471 	int8_t ten_diff_pl = 0;
472 
473 	pdev = wlan_vdev_get_pdev(vdev);
474 	assoc_pdev = wlan_vdev_get_pdev(assoc_vdev);
475 
476 	channel = wlan_vdev_get_active_channel(vdev);
477 	if (channel)
478 		ch_freq = channel->ch_freq;
479 	else
480 		ch_freq = 1;
481 
482 	assoc_channel = wlan_vdev_get_active_channel(assoc_vdev);
483 	if (assoc_channel)
484 		assoc_freq = assoc_channel->ch_freq;
485 	else
486 		assoc_freq = 1;
487 
488 	/*
489 	 *  diff of path loss (of two links) = log10(freq1) - log10(freq2)
490 	 *                       (since distance is constant)
491 	 *  since log10 is not available, we cameup with approximate ranges
492 	 */
493 	log10_freq = (ch_freq * 10) / assoc_freq;
494 	if ((log10_freq >= 20) && (log10_freq < 30))
495 		ten_diff_pl = 4;  /* 0.4 *10 */
496 	else if ((log10_freq >= 11) && (log10_freq < 20))
497 		ten_diff_pl = 1;  /* 0.1 *10 */
498 	else if ((log10_freq >= 8) && (log10_freq < 11))
499 		ten_diff_pl = 0; /* 0 *10 */
500 	else if ((log10_freq >= 4) && (log10_freq < 8))
501 		ten_diff_pl = -1; /* -0.1 * 10 */
502 	else if ((log10_freq >= 1) && (log10_freq < 4))
503 		ten_diff_pl = -4;  /* -0.4 * 10 */
504 
505 	assoc_tx_pow = wlan_reg_get_channel_reg_power_for_freq(assoc_pdev,
506 							       assoc_freq);
507 	tx_pow = wlan_reg_get_channel_reg_power_for_freq(pdev, ch_freq);
508 
509 	diff_txpow = tx_pow -  assoc_tx_pow;
510 
511 	ten_derived_rssi = (diff_txpow * 10) - ten_diff_pl + (rssi * 10);
512 	derived_rssi = ten_derived_rssi / 10;
513 
514 	return derived_rssi;
515 }
516 
mlo_peer_calculate_avg_rssi(struct wlan_mlo_dev_context * ml_dev,struct wlan_mlo_peer_context * ml_peer,int8_t rssi,struct wlan_objmgr_vdev * assoc_vdev)517 static void mlo_peer_calculate_avg_rssi(
518 		struct wlan_mlo_dev_context *ml_dev,
519 		struct wlan_mlo_peer_context *ml_peer,
520 		int8_t rssi,
521 		struct wlan_objmgr_vdev *assoc_vdev)
522 {
523 	int32_t total_rssi = 0;
524 	uint8_t num_psocs = 0;
525 	uint8_t i;
526 	struct wlan_objmgr_vdev *vdev;
527 
528 	for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
529 		vdev = ml_dev->wlan_vdev_list[i];
530 		if (!vdev)
531 			continue;
532 
533 		num_psocs++;
534 		if (vdev == assoc_vdev)
535 			total_rssi += rssi;
536 		else
537 			total_rssi += wlan_vdev_derive_link_rssi(vdev,
538 								 assoc_vdev,
539 								 rssi);
540 	}
541 
542 	if (!num_psocs)
543 		return;
544 
545 	ml_peer->avg_link_rssi = total_rssi / num_psocs;
546 }
547 
548 #ifdef WLAN_MLO_MULTI_CHIP
mlo_get_central_umac_id(uint8_t * psoc_ids)549 int8_t mlo_get_central_umac_id(
550 		uint8_t *psoc_ids)
551 {
552 	uint8_t prim_psoc_id = -1;
553 	uint8_t adjacent = 0;
554 
555 	/* Some 3 link RDPs have restriction on the primary umac.
556 	 * Only the link that is adjacent to both the links can be
557 	 * a primary umac.
558 	 * Note: it means umac migration is also restricted.
559 	 */
560 	mlo_chip_adjacent(psoc_ids[0], psoc_ids[1], &adjacent);
561 	if (!adjacent) {
562 		prim_psoc_id = psoc_ids[2];
563 	} else {
564 		mlo_chip_adjacent(psoc_ids[0], psoc_ids[2], &adjacent);
565 		if (!adjacent) {
566 			prim_psoc_id = psoc_ids[1];
567 		} else {
568 			/* If all links are adjacent to each other,
569 			 * no need to restrict the primary umac.
570 			 * return failure the caller will handle.
571 			 */
572 			mlo_chip_adjacent(psoc_ids[1], psoc_ids[2],
573 					  &adjacent);
574 			if (!adjacent)
575 				prim_psoc_id = psoc_ids[0];
576 			else
577 				return prim_psoc_id;
578 		}
579 	}
580 
581 	return prim_psoc_id;
582 }
583 
mlo_check_topology(struct wlan_objmgr_pdev * pdev,struct wlan_objmgr_vdev * vdev,uint8_t aplinks)584 QDF_STATUS mlo_check_topology(struct wlan_objmgr_pdev *pdev,
585 			      struct wlan_objmgr_vdev *vdev,
586 			      uint8_t aplinks)
587 {
588 	struct wlan_mlo_dev_context *ml_dev = vdev->mlo_dev_ctx;
589 	struct wlan_objmgr_vdev *vdev_iter = NULL;
590 	struct wlan_objmgr_vdev *tmp_vdev = NULL;
591 	uint8_t psoc_ids[WLAN_UMAC_MLO_MAX_VDEVS];
592 	uint8_t i, idx = 0;
593 	uint8_t bridge_umac;
594 	uint8_t adjacent = -1;
595 	uint8_t max_soc;
596 	uint8_t link_id;
597 	bool is_mlo_vdev;
598 
599 	if (!ml_dev)
600 		return QDF_STATUS_E_FAILURE;
601 
602 	/* Do topology check for STA mode for other modes return Success */
603 	if (wlan_vdev_mlme_get_opmode(vdev) != QDF_STA_MODE)
604 		return QDF_STATUS_SUCCESS;
605 
606 	max_soc = mlo_get_total_links(pdev);
607 
608 	if (max_soc != WLAN_UMAC_MLO_MAX_VDEVS) {
609 		/* For Devices which has no topology dependency return Success */
610 		return QDF_STATUS_SUCCESS;
611 	}
612 
613 	if (!ml_dev->bridge_sta_ctx) {
614 		mlo_err("Bridge STA context Null");
615 		return QDF_STATUS_E_FAILURE;
616 	}
617 
618 	/* Incase of 4-LINK RDP in 3-LINK NON-AP MLD mode there is
619 	 * restriction to have the primary umac as central in topology.
620 	 * Note: It also means restriction on umac migration
621 	 */
622 	for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
623 		vdev_iter = vdev->mlo_dev_ctx->wlan_vdev_list[i];
624 		if (!vdev_iter)
625 			continue;
626 		/* Store the psoc_ids of the links */
627 		psoc_ids[idx] = wlan_vdev_get_psoc_id(vdev_iter);
628 		idx++;
629 	}
630 	/* If number of links in AP are greater or equal to STA */
631 	if (aplinks >= idx) {
632 		/* Station has 2 links enabled */
633 		/* Check if the primary umac and assoc links can be different*/
634 		if (idx == (WLAN_UMAC_MLO_MAX_PSOC_TOPOLOGY - 1)) {
635 			mlo_chip_adjacent(psoc_ids[0], psoc_ids[1], &adjacent);
636 			if (adjacent == 1) {
637 				mlo_info("pri umac & assoc link can be diff as chips are adj");
638 				return QDF_STATUS_SUCCESS;
639 			} else {
640 				mlo_info("pri umac & assoc link can be diff but need bridge");
641 				return QDF_STATUS_E_FAILURE;
642 			}
643 		}
644 		/* Check if the primary umac and assoc links are same for 3 link sta*/
645 		if (idx == WLAN_UMAC_MLO_MAX_PSOC_TOPOLOGY) {
646 			bridge_umac = mlo_get_central_umac_id(psoc_ids);
647 
648 			tmp_vdev = mlo_get_link_vdev_from_psoc_id(ml_dev,
649 								  bridge_umac,
650 								  false);
651 
652 			if (!tmp_vdev)
653 				return QDF_STATUS_E_FAILURE;
654 
655 			link_id = tmp_vdev->vdev_mlme.mlo_link_id;
656 			if (bridge_umac != -1) {
657 				if (wlan_vdev_get_psoc_id(vdev) != bridge_umac) {
658 					mlo_err("Central LINK %d Force central as primary umac!! ",
659 						bridge_umac);
660 					tmp_vdev->vdev_objmgr.mlo_central_vdev = true;
661 					ml_dev->bridge_sta_ctx->is_force_central_primary = true;
662 					ml_dev->bridge_sta_ctx->bridge_umac_id = bridge_umac;
663 					ml_dev->bridge_sta_ctx->bridge_link_id = link_id;
664 					wlan_objmgr_vdev_release_ref(tmp_vdev, WLAN_MLO_MGR_ID);
665 					return QDF_STATUS_SUCCESS;
666 				}
667 			}
668 		}
669 	} else {
670 		/* If # of links in AP < then link on Station check for bridge vap */
671 		/* Check case when AP MLD is 2 link and NON-AP MLD is 3 link capable*/
672 		if (idx == WLAN_UMAC_MLO_MAX_PSOC_TOPOLOGY &&
673 		    (aplinks == (WLAN_UMAC_MLO_MAX_PSOC_TOPOLOGY - 1))) {
674 			bridge_umac = mlo_get_central_umac_id(psoc_ids);
675 			tmp_vdev = mlo_get_link_vdev_from_psoc_id(ml_dev,
676 								  bridge_umac,
677 								  false);
678 
679 			if (!tmp_vdev)
680 				return QDF_STATUS_E_FAILURE;
681 
682 			link_id = tmp_vdev->vdev_mlme.mlo_link_id;
683 			if (bridge_umac != -1) {
684 				if (wlan_vdev_get_psoc_id(vdev) != bridge_umac) {
685 					is_mlo_vdev = wlan_vdev_mlme_is_mlo_vdev(tmp_vdev);
686 					if (is_mlo_vdev) {
687 						mlo_err("Central Link %d partipating in Assoc!! ",
688 							bridge_umac);
689 					} else {
690 						mlo_err("Central %d not part of Assoc create bridge!!",
691 							bridge_umac);
692 						tmp_vdev->vdev_objmgr.mlo_central_vdev = true;
693 						ml_dev->bridge_sta_ctx->is_force_central_primary = true;
694 						ml_dev->bridge_sta_ctx->bridge_umac_id = bridge_umac;
695 						ml_dev->bridge_sta_ctx->bridge_vap_exists = true;
696 						ml_dev->bridge_sta_ctx->bridge_link_id = WDS_BRIDGE_VDEV_LINK_ID;
697 					}
698 				}
699 			}
700 		}
701 	}
702 	if (tmp_vdev)
703 		wlan_objmgr_vdev_release_ref(tmp_vdev, WLAN_MLO_MGR_ID);
704 	return QDF_STATUS_SUCCESS;
705 }
706 
mlo_update_partner_bridge_info(struct wlan_mlo_dev_context * ml_dev,struct mlo_partner_info * partner_info)707 void mlo_update_partner_bridge_info(struct wlan_mlo_dev_context *ml_dev,
708 				    struct mlo_partner_info *partner_info)
709 {
710 	struct wlan_objmgr_vdev *bridge_vdev = NULL;
711 	uint8_t bridge_umac_id = -1;
712 	uint8_t bridge_index = partner_info->num_partner_links;
713 
714 	if (!ml_dev || !ml_dev->bridge_sta_ctx)
715 		return;
716 
717 	bridge_umac_id = ml_dev->bridge_sta_ctx->bridge_umac_id;
718 	bridge_vdev = mlo_get_link_vdev_from_psoc_id(ml_dev, bridge_umac_id, false);
719 	if (bridge_vdev) {
720 		partner_info->partner_link_info[bridge_index].link_id = bridge_vdev->vdev_mlme.mlo_link_id;
721 		qdf_mem_copy(&partner_info->partner_link_info[bridge_index].link_addr,
722 			     wlan_vdev_mlme_get_macaddr(bridge_vdev), sizeof(struct qdf_mac_addr));
723 		/* Account for bridge peer here */
724 		partner_info->num_partner_links++;
725 		wlan_objmgr_vdev_release_ref(bridge_vdev, WLAN_MLO_MGR_ID);
726 	}
727 }
728 
mlo_is_sta_bridge_vdev(struct wlan_objmgr_vdev * vdev)729 bool mlo_is_sta_bridge_vdev(struct wlan_objmgr_vdev *vdev)
730 {
731 	struct wlan_mlo_dev_context *ml_dev = NULL;
732 
733 	if (!vdev)
734 		return false;
735 
736 	ml_dev = vdev->mlo_dev_ctx;
737 
738 	if (!ml_dev || !ml_dev->bridge_sta_ctx)
739 		return false;
740 
741 	if (vdev->vdev_objmgr.mlo_central_vdev &&
742 	    ml_dev->bridge_sta_ctx->bridge_vap_exists)
743 		return true;
744 
745 	return false;
746 }
747 
748 qdf_export_symbol(mlo_is_sta_bridge_vdev);
749 
mlo_sta_bridge_exists(struct wlan_objmgr_vdev * vdev)750 bool mlo_sta_bridge_exists(struct wlan_objmgr_vdev *vdev)
751 {
752 	struct wlan_mlo_dev_context *ml_dev = NULL;
753 
754 	if (!vdev)
755 		return false;
756 
757 	ml_dev = vdev->mlo_dev_ctx;
758 
759 	if (!ml_dev || !ml_dev->bridge_sta_ctx)
760 		return false;
761 
762 	if (ml_dev->bridge_sta_ctx->bridge_vap_exists)
763 		return true;
764 
765 	return false;
766 }
767 
768 qdf_export_symbol(mlo_sta_bridge_exists);
769 
mlo_is_force_central_primary(struct wlan_objmgr_vdev * vdev)770 bool mlo_is_force_central_primary(struct wlan_objmgr_vdev *vdev)
771 {
772 	struct wlan_mlo_dev_context *ml_dev = NULL;
773 
774 	if (!vdev)
775 		return false;
776 
777 	ml_dev = vdev->mlo_dev_ctx;
778 
779 	if (!ml_dev || !ml_dev->bridge_sta_ctx)
780 		return false;
781 
782 	if (ml_dev->bridge_sta_ctx->is_force_central_primary)
783 		return true;
784 
785 	return false;
786 }
787 
788 qdf_export_symbol(mlo_is_force_central_primary);
789 
mlo_get_total_links(struct wlan_objmgr_pdev * pdev)790 uint8_t mlo_get_total_links(struct wlan_objmgr_pdev *pdev)
791 {
792 	uint8_t ml_grp_id;
793 
794 	ml_grp_id = wlan_get_mlo_grp_id_from_pdev(pdev);
795 	return mlo_setup_get_total_socs(ml_grp_id);
796 }
797 
mlo_set_3_link_primary_umac(struct wlan_mlo_peer_context * ml_peer,struct wlan_objmgr_vdev * link_vdevs[])798 static QDF_STATUS mlo_set_3_link_primary_umac(
799 		struct wlan_mlo_peer_context *ml_peer,
800 		struct wlan_objmgr_vdev *link_vdevs[])
801 {
802 	uint8_t psoc_ids[WLAN_UMAC_MLO_MAX_VDEVS];
803 	int8_t central_umac_id;
804 
805 	if (ml_peer->max_links != 3)
806 		return QDF_STATUS_E_FAILURE;
807 
808 	/* Some 3 link RDPs have restriction on the primary umac.
809 	 * Only the link that is adjacent to both the links can be
810 	 * a primary umac.
811 	 * Note: it means umac migration is also restricted.
812 	 */
813 	psoc_ids[0] = wlan_vdev_get_psoc_id(link_vdevs[0]);
814 	psoc_ids[1] = wlan_vdev_get_psoc_id(link_vdevs[1]);
815 	psoc_ids[2] = wlan_vdev_get_psoc_id(link_vdevs[2]);
816 
817 	central_umac_id = mlo_get_central_umac_id(psoc_ids);
818 	if (central_umac_id != -1)
819 		ml_peer->primary_umac_psoc_id = central_umac_id;
820 	else
821 		return QDF_STATUS_E_FAILURE;
822 
823 	mlo_peer_assign_primary_umac(ml_peer,
824 				     &ml_peer->peer_list[0]);
825 
826 	return QDF_STATUS_SUCCESS;
827 }
828 #else
mlo_set_3_link_primary_umac(struct wlan_mlo_peer_context * ml_peer,struct wlan_objmgr_vdev * link_vdevs[])829 static QDF_STATUS mlo_set_3_link_primary_umac(
830 		struct wlan_mlo_peer_context *ml_peer,
831 		struct wlan_objmgr_vdev *link_vdevs[])
832 {
833 	return QDF_STATUS_E_FAILURE;
834 }
835 #endif
836 
mlo_peer_allocate_primary_umac(struct wlan_mlo_dev_context * ml_dev,struct wlan_mlo_peer_context * ml_peer,struct wlan_objmgr_vdev * link_vdevs[])837 QDF_STATUS mlo_peer_allocate_primary_umac(
838 		struct wlan_mlo_dev_context *ml_dev,
839 		struct wlan_mlo_peer_context *ml_peer,
840 		struct wlan_objmgr_vdev *link_vdevs[])
841 {
842 	struct wlan_mlo_link_peer_entry *peer_entry;
843 	struct wlan_objmgr_peer *assoc_peer = NULL;
844 	int32_t rssi;
845 	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
846 	uint8_t first_link_id = 0;
847 	bool primary_umac_set = false;
848 	uint8_t i, psoc_id;
849 
850 	peer_entry = &ml_peer->peer_list[0];
851 	assoc_peer = peer_entry->link_peer;
852 	if (!assoc_peer)
853 		return QDF_STATUS_E_FAILURE;
854 
855 	/* For Station mode, assign assoc peer as primary umac */
856 	if (wlan_peer_get_peer_type(assoc_peer) == WLAN_PEER_AP) {
857 		mlo_peer_assign_primary_umac(ml_peer, peer_entry);
858 		mlo_info("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " primary umac soc %d ",
859 			 ml_dev->mld_id,
860 			 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes),
861 			 ml_peer->primary_umac_psoc_id);
862 
863 		return QDF_STATUS_SUCCESS;
864 	}
865 
866 	/* Select assoc peer's PSOC as primary UMAC in Multi-chip solution,
867 	 * 1) for single link MLO connection
868 	 * 2) if MLD is single chip MLO
869 	 */
870 	if ((mlo_ctx->force_non_assoc_prim_umac) &&
871 	    (ml_peer->max_links >= 1)) {
872 		for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
873 			if (!link_vdevs[i])
874 				continue;
875 
876 			if (wlan_peer_get_vdev(assoc_peer) == link_vdevs[i])
877 				continue;
878 			psoc_id = wlan_vdev_get_psoc_id(link_vdevs[i]);
879 			ml_peer->primary_umac_psoc_id = psoc_id;
880 			break;
881 		}
882 
883 		mlo_peer_assign_primary_umac(ml_peer, peer_entry);
884 		mlo_info("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT
885 			 " primary umac soc %d ", ml_dev->mld_id,
886 			 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes),
887 			 ml_peer->primary_umac_psoc_id);
888 
889 		return QDF_STATUS_SUCCESS;
890 	}
891 
892 	if ((ml_peer->max_links == 1) ||
893 	    (mlo_vdevs_check_single_soc(link_vdevs, ml_peer->max_links))) {
894 		mlo_peer_assign_primary_umac(ml_peer, peer_entry);
895 		mlo_info("MLD ID %d Assoc peer " QDF_MAC_ADDR_FMT
896 			 " primary umac soc %d ", ml_dev->mld_id,
897 			 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes),
898 			 ml_peer->primary_umac_psoc_id);
899 
900 		return QDF_STATUS_SUCCESS;
901 	}
902 
903 	if (mlo_set_3_link_primary_umac(ml_peer, link_vdevs) ==
904 	    QDF_STATUS_SUCCESS) {
905 		/* If success then the primary umac is restricted and assigned.
906 		 * if not, there is no restriction, so just fallthrough
907 		 */
908 		mlo_info("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT
909 			 " center primary umac soc %d ",
910 			 ml_dev->mld_id,
911 			 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes),
912 			 ml_peer->primary_umac_psoc_id);
913 
914 		return QDF_STATUS_SUCCESS;
915 	}
916 
917 	if (mlo_ctx->mlo_is_force_primary_umac) {
918 		for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
919 			if (!link_vdevs[i])
920 				continue;
921 
922 			psoc_id = wlan_vdev_get_psoc_id(link_vdevs[i]);
923 			if (!first_link_id)
924 				first_link_id = psoc_id;
925 
926 			if (psoc_id == mlo_ctx->mlo_forced_primary_umac_id) {
927 				ml_peer->primary_umac_psoc_id = psoc_id;
928 				primary_umac_set = true;
929 				break;
930 			}
931 		}
932 
933 		if (!primary_umac_set)
934 			ml_peer->primary_umac_psoc_id = first_link_id;
935 
936 		mlo_peer_assign_primary_umac(ml_peer, peer_entry);
937 		mlo_info("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " primary umac soc %d ",
938 			 ml_dev->mld_id,
939 			 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes),
940 			 ml_peer->primary_umac_psoc_id);
941 
942 		return QDF_STATUS_SUCCESS;
943 	}
944 
945 	rssi = wlan_peer_get_rssi(assoc_peer);
946 	mlo_peer_calculate_avg_rssi(ml_dev, ml_peer, rssi,
947 				    wlan_peer_get_vdev(assoc_peer));
948 
949 	ml_peer->primary_umac_psoc_id =
950 		wlan_mld_get_best_primary_umac_w_rssi(ml_peer, link_vdevs, false);
951 
952 	mlo_peer_assign_primary_umac(ml_peer, peer_entry);
953 
954 	mlo_info("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " avg RSSI %d primary umac soc %d ",
955 		 ml_dev->mld_id,
956 		 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes),
957 		 ml_peer->avg_link_rssi, ml_peer->primary_umac_psoc_id);
958 
959 	return QDF_STATUS_SUCCESS;
960 }
961 
mlo_peer_free_primary_umac(struct wlan_mlo_dev_context * ml_dev,struct wlan_mlo_peer_context * ml_peer)962 QDF_STATUS mlo_peer_free_primary_umac(
963 		struct wlan_mlo_dev_context *ml_dev,
964 		struct wlan_mlo_peer_context *ml_peer)
965 {
966 	return QDF_STATUS_SUCCESS;
967 }
968 
969 #ifdef QCA_SUPPORT_PRIMARY_LINK_MIGRATE
wlan_objmgr_mlo_update_primary_info(struct wlan_objmgr_peer * peer)970 void wlan_objmgr_mlo_update_primary_info(struct wlan_objmgr_peer *peer)
971 {
972 	struct wlan_mlo_peer_context *ml_peer = NULL;
973 	struct wlan_mlo_link_peer_entry *peer_ent_iter;
974 	uint8_t i;
975 
976 	ml_peer = peer->mlo_peer_ctx;
977 	wlan_mlo_peer_wsi_link_delete(ml_peer);
978 	ml_peer->primary_umac_psoc_id = wlan_peer_get_psoc_id(peer);
979 
980 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
981 		peer_ent_iter = &ml_peer->peer_list[i];
982 
983 		if (!peer_ent_iter->link_peer)
984 			continue;
985 
986 		if (peer_ent_iter->is_primary)
987 			peer_ent_iter->is_primary = false;
988 
989 		if (peer_ent_iter->link_peer == peer)
990 			peer_ent_iter->is_primary = true;
991 	}
992 	wlan_mlo_peer_wsi_link_add(ml_peer);
993 }
994 
995 qdf_export_symbol(wlan_objmgr_mlo_update_primary_info);
996 
mlo_mlme_ptqm_migrate_timer_cb(void * arg)997 void mlo_mlme_ptqm_migrate_timer_cb(void *arg)
998 {
999 	struct wlan_mlo_dev_context *ml_dev = (struct wlan_mlo_dev_context *)arg;
1000 	struct wlan_mlo_peer_context *ml_peer = NULL;
1001 	uint16_t i = 0;
1002 
1003 	if (!ml_dev)
1004 		return;
1005 
1006 	/* Check for pending bitmaps and issue disconnect */
1007 	for (i = 0; i < MAX_MLO_PEER_ID; i++) {
1008 		if (qdf_test_bit(i, ml_dev->mlo_peer_id_bmap)) {
1009 			ml_peer = wlan_mlo_get_mlpeer_by_ml_peerid(ml_dev, i);
1010 			if (ml_peer && ml_peer->primary_umac_migration_in_progress) {
1011 				ml_peer->primary_umac_migration_in_progress = false;
1012 				mlo_err("Issue disconnect for ml peer with ml peer id:%d", i);
1013 				wlan_mlo_peer_deauth_init(ml_peer,
1014 							  NULL, 0);
1015 			}
1016 			qdf_clear_bit(i, ml_dev->mlo_peer_id_bmap);
1017 		}
1018 	}
1019 }
1020 
1021 /**
1022  * mlo_ptqm_list_peek_head() - Returns the head of linked list
1023  *
1024  * @ptqm_list: Pointer to the list of peer ptqm migrate entries
1025  *
1026  * API to retrieve the head from the list of peer ptqm migrate entries
1027  *
1028  * Return: Pointer to peer ptqm migrate entry
1029  */
1030 static
mlo_ptqm_list_peek_head(qdf_list_t * ptqm_list)1031 struct peer_ptqm_migrate_list_entry *mlo_ptqm_list_peek_head(
1032 					qdf_list_t *ptqm_list)
1033 {
1034 	struct peer_ptqm_migrate_list_entry *peer_entry;
1035 	qdf_list_node_t *peer_node = NULL;
1036 
1037 	if (qdf_list_peek_front(ptqm_list, &peer_node) != QDF_STATUS_SUCCESS)
1038 		return NULL;
1039 
1040 	peer_entry = qdf_container_of(peer_node,
1041 				      struct peer_ptqm_migrate_list_entry,
1042 				      node);
1043 
1044 	return peer_entry;
1045 }
1046 
1047 /**
1048  * mlo_get_next_peer_ctx() - Return next peer ptqm entry from the list
1049  *
1050  * @peer_list:  Pointer to the list of peer ptqm migrate entries
1051  * @peer_cur: Pointer to the current peer ptqm entry
1052  *
1053  * API to retrieve the next node from the list of peer ptqm migrate entries
1054  *
1055  * Return: Pointer to peer ptqm migrate entry
1056  */
1057 static
mlo_get_next_peer_ctx(qdf_list_t * peer_list,struct peer_ptqm_migrate_list_entry * peer_cur)1058 struct peer_ptqm_migrate_list_entry *mlo_get_next_peer_ctx(
1059 				qdf_list_t *peer_list,
1060 				struct peer_ptqm_migrate_list_entry *peer_cur)
1061 {
1062 	struct peer_ptqm_migrate_list_entry *peer_next;
1063 	qdf_list_node_t *node = &peer_cur->node;
1064 	qdf_list_node_t *next_node = NULL;
1065 
1066 	/* This API is invoked with lock acquired, do not add log prints */
1067 	if (!node)
1068 		return NULL;
1069 
1070 	if (qdf_list_peek_next(peer_list, node, &next_node) !=
1071 						QDF_STATUS_SUCCESS)
1072 		return NULL;
1073 
1074 	peer_next = qdf_container_of(next_node,
1075 				     struct peer_ptqm_migrate_list_entry,
1076 				     node);
1077 	return peer_next;
1078 }
1079 
1080 /**
1081  * wlan_mlo_send_ptqm_migrate_cmd() - API to send WMI to trigger ptqm migration
1082  * @vdev: objmgr vdev object
1083  * @list: peer list to be migrated
1084  * @num_peers_failed: number of peers for which wmi cmd is failed.
1085  * This value is expected to be used only in case failure is returned by WMI
1086  *
1087  * API to send WMI to trigger ptqm migration
1088  *
1089  * Return: QDF_STATUS
1090  */
1091 static QDF_STATUS
wlan_mlo_send_ptqm_migrate_cmd(struct wlan_objmgr_vdev * vdev,struct peer_migrate_ptqm_multi_entries * list,uint16_t * num_peers_failed)1092 wlan_mlo_send_ptqm_migrate_cmd(struct wlan_objmgr_vdev *vdev,
1093 			       struct peer_migrate_ptqm_multi_entries *list,
1094 			       uint16_t *num_peers_failed)
1095 {
1096 	struct wlan_lmac_if_mlo_tx_ops *mlo_tx_ops;
1097 	struct wlan_objmgr_psoc *psoc;
1098 	QDF_STATUS status;
1099 	struct peer_ptqm_migrate_params param = {0};
1100 	struct peer_ptqm_migrate_entry *peer_list = NULL;
1101 	struct peer_ptqm_migrate_list_entry *peer_entry, *next_entry;
1102 	struct wlan_mlo_dev_context *ml_dev = NULL;
1103 	uint16_t i = 0;
1104 
1105 	ml_dev = vdev->mlo_dev_ctx;
1106 	if (!ml_dev)
1107 		return QDF_STATUS_E_FAILURE;
1108 
1109 	psoc = wlan_vdev_get_psoc(vdev);
1110 	if (!psoc) {
1111 		mlo_err("null psoc");
1112 		return QDF_STATUS_E_NULL_VALUE;
1113 	}
1114 
1115 	mlo_tx_ops = &psoc->soc_cb.tx_ops->mlo_ops;
1116 	if (!mlo_tx_ops || !mlo_tx_ops->peer_ptqm_migrate_send) {
1117 		mlo_err("mlo_tx_ops is null!");
1118 		return QDF_STATUS_E_NULL_VALUE;
1119 	}
1120 
1121 	param.vdev_id = wlan_vdev_get_id(vdev);
1122 	param.num_peers = list->num_entries;
1123 
1124 	param.peer_list = qdf_mem_malloc(sizeof(struct peer_ptqm_migrate_entry) *
1125 					 list->num_entries);
1126 	if (!param.peer_list) {
1127 		mlo_err("Failed to allocate memory for ptqm migration command");
1128 		return QDF_STATUS_E_FAILURE;
1129 	}
1130 
1131 	peer_list = param.peer_list;
1132 
1133 	peer_entry = mlo_ptqm_list_peek_head(&list->peer_list);
1134 	while (peer_entry) {
1135 		peer_list[i].ml_peer_id = peer_entry->mlo_peer_id;
1136 		peer_list[i].hw_link_id = peer_entry->new_hw_link_id;
1137 
1138 		qdf_set_bit(peer_entry->mlo_peer_id,
1139 			    ml_dev->mlo_peer_id_bmap);
1140 
1141 		mlo_debug("idx:%d, ml_peer_id:%d, hw_link_id:%d",
1142 			  i, peer_list[i].ml_peer_id,
1143 			  peer_list[i].hw_link_id);
1144 		i++;
1145 		next_entry = mlo_get_next_peer_ctx(&list->peer_list,
1146 						   peer_entry);
1147 		peer_entry = next_entry;
1148 	}
1149 
1150 	status = mlo_tx_ops->peer_ptqm_migrate_send(vdev, &param);
1151 	if (QDF_IS_STATUS_ERROR(status)) {
1152 		mlo_err("Failed to send WMI for ptqm migration");
1153 		*num_peers_failed = param.num_peers_failed;
1154 		qdf_mem_free(param.peer_list);
1155 		return QDF_STATUS_E_FAILURE;
1156 	}
1157 
1158 	/* Set timeout equal to peer delete timeout as requested by FW.
1159 	 * Timeout value to be optimized later. Timeout value will be
1160 	 * updated later based on stress testings.
1161 	 */
1162 	qdf_timer_mod(&ml_dev->ptqm_migrate_timer,
1163 		      ML_PRIMARY_TQM_MIGRATRION_TIMEOUT);
1164 
1165 	qdf_mem_free(param.peer_list);
1166 	return QDF_STATUS_SUCCESS;
1167 }
1168 
1169 /**
1170  * wlan_mlo_get_new_ptqm_id() - API to get new ptqm ID
1171  * @curr_vdev: objmgr vdev object for current primary link
1172  * @ml_peer: ml peer object
1173  * @new_primary_link_id: new primary link id
1174  * @new_hw_link_id: hw link id for new primary TQM
1175  * @force_mig: allow migration to vdevs which are disabled to be pumac
1176  * using primary_umac_skip ini
1177  *
1178  * API to get new ptqm ID
1179  *
1180  * Return: QDF_STATUS
1181  */
1182 static QDF_STATUS
wlan_mlo_get_new_ptqm_id(struct wlan_objmgr_vdev * curr_vdev,struct wlan_mlo_peer_context * ml_peer,uint8_t new_primary_link_id,uint16_t * new_hw_link_id,bool force_mig)1183 wlan_mlo_get_new_ptqm_id(struct wlan_objmgr_vdev *curr_vdev,
1184 			 struct wlan_mlo_peer_context *ml_peer,
1185 			 uint8_t new_primary_link_id,
1186 			 uint16_t *new_hw_link_id,
1187 			 bool force_mig)
1188 {
1189 	uint8_t current_primary_link_id = WLAN_LINK_ID_INVALID;
1190 	struct wlan_objmgr_vdev *tmp_vdev = NULL;
1191 	struct wlan_objmgr_vdev *wlan_vdev_list[WLAN_UMAC_MLO_MAX_VDEVS] = { NULL };
1192 	struct wlan_objmgr_vdev *tmp_vdev_list[WLAN_UMAC_MLO_MAX_VDEVS] = { NULL };
1193 	struct wlan_mlo_link_peer_entry *peer_entry;
1194 	uint8_t psoc_ids[WLAN_UMAC_MLO_MAX_VDEVS];
1195 	struct wlan_objmgr_vdev *link_vdev = NULL;
1196 	struct wlan_objmgr_peer *curr_peer = NULL;
1197 	QDF_STATUS status;
1198 	uint8_t i = 0, idx = 0, j = 0, tmp_cnt = 0;
1199 
1200 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
1201 		peer_entry = &ml_peer->peer_list[i];
1202 		if (!peer_entry || !peer_entry->link_peer)
1203 			continue;
1204 
1205 		if (peer_entry->is_primary) {
1206 			curr_peer = peer_entry->link_peer;
1207 			break;
1208 		}
1209 	}
1210 
1211 	if (!curr_peer) {
1212 		mlo_err("ML peer " QDF_MAC_ADDR_FMT " current primary link not found",
1213 			QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes));
1214 		return QDF_STATUS_E_INVAL;
1215 	}
1216 
1217 	if (wlan_vdev_mlme_get_opmode(curr_vdev) == QDF_SAP_MODE &&
1218 	    wlan_peer_mlme_get_state(curr_peer) != WLAN_CONNECTED_STATE) {
1219 		mlo_err("ML peer " QDF_MAC_ADDR_FMT " is not authorized",
1220 			QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes));
1221 		return QDF_STATUS_E_INVAL;
1222 	}
1223 
1224 	*new_hw_link_id = INVALID_HW_LINK_ID;
1225 	current_primary_link_id =
1226 		wlan_mlo_peer_get_primary_peer_link_id_by_ml_peer(ml_peer);
1227 	if (current_primary_link_id == WLAN_LINK_ID_INVALID) {
1228 		mlo_err("ML peer " QDF_MAC_ADDR_FMT "current primary link id is invalid",
1229 			QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes));
1230 		return QDF_STATUS_E_INVAL;
1231 	}
1232 
1233 	if (current_primary_link_id == new_primary_link_id) {
1234 		mlo_err("current and requested link_id are same");
1235 		return QDF_STATUS_E_INVAL;
1236 	}
1237 
1238 	if (new_primary_link_id != WLAN_LINK_ID_INVALID) {
1239 		link_vdev = mlo_get_vdev_by_link_id(curr_vdev,
1240 						    new_primary_link_id,
1241 						    WLAN_MLO_MGR_ID);
1242 		if (!link_vdev) {
1243 			mlo_err("links vdev not found for link id %d",
1244 				new_primary_link_id);
1245 			return QDF_STATUS_E_INVAL;
1246 		}
1247 
1248 		if (wlan_vdev_read_skip_pumac_cnt(link_vdev) > 0) {
1249 			mlo_err("Selected new ptqm link not allowed for migration");
1250 			mlo_release_vdev_ref(link_vdev);
1251 			return QDF_STATUS_E_PERM;
1252 		}
1253 		mlo_release_vdev_ref(link_vdev);
1254 	}
1255 
1256 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
1257 		peer_entry = &ml_peer->peer_list[i];
1258 		if (!peer_entry || !peer_entry->link_peer)
1259 			continue;
1260 
1261 		if (wlan_peer_get_peer_type(peer_entry->link_peer) ==
1262 					WLAN_PEER_MLO_BRIDGE)
1263 			goto exit;
1264 
1265 		psoc_ids[j++] = wlan_vdev_get_psoc_id(
1266 				wlan_peer_get_vdev(peer_entry->link_peer));
1267 	}
1268 
1269 	/* For some 3 link RDPs, there is restriction on primary umac */
1270 	if (j == 3) {
1271 		if (mlo_get_central_umac_id(psoc_ids) != -1) {
1272 			mlo_err("ML peer " QDF_MAC_ADDR_FMT "migration not supported",
1273 				QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes));
1274 			goto exit;
1275 		}
1276 	}
1277 
1278 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
1279 		peer_entry = &ml_peer->peer_list[i];
1280 		if (!peer_entry || !peer_entry->link_peer)
1281 			continue;
1282 
1283 		tmp_vdev = wlan_peer_get_vdev(peer_entry->link_peer);
1284 		if (!tmp_vdev || tmp_vdev == curr_vdev)
1285 			continue;
1286 
1287 		status = wlan_objmgr_vdev_try_get_ref(tmp_vdev,
1288 						      WLAN_MLME_SB_ID);
1289 		if (QDF_IS_STATUS_ERROR(status)) {
1290 			mlo_err("failed to get vdev ref");
1291 			continue;
1292 		}
1293 
1294 		if (wlan_vdev_read_skip_pumac_cnt(tmp_vdev) > 0) {
1295 			mlo_debug("Vdev not allowed for migration, skip this vdev");
1296 			wlan_objmgr_vdev_release_ref(tmp_vdev,
1297 						     WLAN_MLME_SB_ID);
1298 			continue;
1299 		}
1300 
1301 		/* Store vdevs which cannot be selected as primary in a temp
1302 		 * list. force_mig flag will be used to allow migration to vdevs
1303 		 * which are not allowed to be selected as primary by using the
1304 		 * primary_umac_skip ini config. This will be helpful in scenarios
1305 		 * where if the current primary link is going down and peer ptqm
1306 		 * needs to be migrated but the partner links ofthat mld are
1307 		 * the user disabled links for ptqm.
1308 		 */
1309 		if (wlan_vdev_skip_pumac(tmp_vdev)) {
1310 			mlo_debug("Vdev cannot be selected as primary");
1311 			tmp_vdev_list[tmp_cnt++] = tmp_vdev;
1312 			continue;
1313 		}
1314 		wlan_vdev_list[idx++] = tmp_vdev;
1315 	}
1316 
1317 	if (new_primary_link_id == WLAN_LINK_ID_INVALID) {
1318 		mlo_debug("Invalid link id provided, select new link id");
1319 		/* If there are no vdevs present in wlan_vdev_list, means none
1320 		 * of the partner vdevs of current MLD are eligible to become
1321 		 * primary umac. In that case if user has requested force
1322 		 * migration and there are some vdevs present in temp_vdev_list,
1323 		 * select new primary umac from those vdev. If no vdevs are
1324 		 * prenset in any of the list, return failure.
1325 		 */
1326 		if (idx == 0) {
1327 			if (!force_mig || tmp_cnt == 0) {
1328 				mlo_err("No link available to be selected as primary");
1329 				goto exit;
1330 			} else {
1331 				ml_peer->migrate_primary_umac_psoc_id =
1332 					wlan_mld_get_best_primary_umac_w_rssi(
1333 							ml_peer,
1334 							tmp_vdev_list,
1335 							true);
1336 				if (ml_peer->migrate_primary_umac_psoc_id ==
1337 						ML_PRIMARY_UMAC_ID_INVAL) {
1338 					mlo_err("Unable to fetch new primary link id for ml peer " QDF_MAC_ADDR_FMT,
1339 						QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes));
1340 					goto exit;
1341 				}
1342 
1343 				for (i = 0; i < tmp_cnt; i++) {
1344 					if (ml_peer->migrate_primary_umac_psoc_id ==
1345 							wlan_vdev_get_psoc_id(tmp_vdev_list[i])) {
1346 						*new_hw_link_id = wlan_mlo_get_pdev_hw_link_id(
1347 								wlan_vdev_get_pdev(tmp_vdev_list[i]));
1348 						break;
1349 					}
1350 				}
1351 			}
1352 		} else {
1353 			ml_peer->migrate_primary_umac_psoc_id =
1354 				wlan_mld_get_best_primary_umac_w_rssi(
1355 							ml_peer,
1356 							wlan_vdev_list,
1357 							false);
1358 			if (ml_peer->migrate_primary_umac_psoc_id ==
1359 					ML_PRIMARY_UMAC_ID_INVAL) {
1360 				mlo_err("Unable to fetch new primary link id for ml peer " QDF_MAC_ADDR_FMT,
1361 					QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes));
1362 				goto exit;
1363 			}
1364 			for (i = 0; i < idx; i++) {
1365 				if (ml_peer->migrate_primary_umac_psoc_id ==
1366 						wlan_vdev_get_psoc_id(wlan_vdev_list[i])) {
1367 					*new_hw_link_id = wlan_mlo_get_pdev_hw_link_id(
1368 							wlan_vdev_get_pdev(wlan_vdev_list[i]));
1369 					break;
1370 				}
1371 			}
1372 		}
1373 	} else {
1374 		/* check if provided link id is part of current ml peer links */
1375 		for (i = 0; i < idx; i++) {
1376 			if (new_primary_link_id == wlan_vdev_get_link_id(wlan_vdev_list[i])) {
1377 				*new_hw_link_id = wlan_mlo_get_pdev_hw_link_id(
1378 							wlan_vdev_get_pdev(wlan_vdev_list[i]));
1379 				ml_peer->migrate_primary_umac_psoc_id =
1380 						wlan_vdev_get_psoc_id(wlan_vdev_list[i]);
1381 				break;
1382 			}
1383 		}
1384 		if (*new_hw_link_id == INVALID_HW_LINK_ID && force_mig) {
1385 			for (i = 0; i < tmp_cnt; i++) {
1386 				if (new_primary_link_id ==
1387 				    wlan_vdev_get_link_id(tmp_vdev_list[i])) {
1388 					*new_hw_link_id = wlan_mlo_get_pdev_hw_link_id(
1389 								wlan_vdev_get_pdev(tmp_vdev_list[i]));
1390 					ml_peer->migrate_primary_umac_psoc_id =
1391 							wlan_vdev_get_psoc_id(tmp_vdev_list[i]);
1392 					break;
1393 				}
1394 			}
1395 		}
1396 	}
1397 
1398 	if (*new_hw_link_id == INVALID_HW_LINK_ID) {
1399 		mlo_err("New primary link id not found for ml peer " QDF_MAC_ADDR_FMT,
1400 			QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes));
1401 		goto exit;
1402 	}
1403 
1404 	for (i = 0; i < idx; i++)
1405 		wlan_objmgr_vdev_release_ref(wlan_vdev_list[i],
1406 					     WLAN_MLME_SB_ID);
1407 
1408 	for (i = 0; i < tmp_cnt; i++)
1409 		wlan_objmgr_vdev_release_ref(tmp_vdev_list[i],
1410 					     WLAN_MLME_SB_ID);
1411 	return QDF_STATUS_SUCCESS;
1412 
1413 exit:
1414 	ml_peer->migrate_primary_umac_psoc_id = ML_PRIMARY_UMAC_ID_INVAL;
1415 
1416 	for (i = 0; i < idx; i++)
1417 		wlan_objmgr_vdev_release_ref(wlan_vdev_list[i],
1418 					     WLAN_MLME_SB_ID);
1419 
1420 	for (i = 0; i < tmp_cnt; i++)
1421 		wlan_objmgr_vdev_release_ref(tmp_vdev_list[i],
1422 					     WLAN_MLME_SB_ID);
1423 	return QDF_STATUS_E_FAILURE;
1424 }
1425 
1426 /**
1427  * wlan_mlo_free_ptqm_migrate_list() - API to free peer ptqm migration list
1428  * @list: peer ptqm migration list
1429  *
1430  * API to free peer ptqm migration list
1431  *
1432  * Return: void
1433  */
wlan_mlo_free_ptqm_migrate_list(struct peer_migrate_ptqm_multi_entries * list)1434 static void wlan_mlo_free_ptqm_migrate_list(
1435 			struct peer_migrate_ptqm_multi_entries *list)
1436 {
1437 	struct peer_ptqm_migrate_list_entry *peer_entry, *next_entry;
1438 
1439 	peer_entry = mlo_ptqm_list_peek_head(&list->peer_list);
1440 	while (peer_entry) {
1441 		list->num_entries--;
1442 		next_entry = mlo_get_next_peer_ctx(&list->peer_list,
1443 						   peer_entry);
1444 		if (peer_entry->peer)
1445 			wlan_objmgr_peer_release_ref(peer_entry->peer,
1446 						     WLAN_MLME_SB_ID);
1447 		qdf_list_remove_node(&list->peer_list, &peer_entry->node);
1448 		qdf_mem_free(peer_entry);
1449 		peer_entry = next_entry;
1450 	}
1451 	qdf_list_destroy(&list->peer_list);
1452 }
1453 
1454 /**
1455  * wlan_mlo_reset_ptqm_migrate_list() - API to reset peer ptqm migration list
1456  * @ml_dev: MLO dev context
1457  * @list: peer ptqm migration list
1458  * @num_peers_failed: number of peers for which wmi cmd is failed.
1459  *
1460  * API to reset peer ptqm migration list
1461  *
1462  * Return: void
1463  */
wlan_mlo_reset_ptqm_migrate_list(struct wlan_mlo_dev_context * ml_dev,struct peer_migrate_ptqm_multi_entries * list,uint16_t num_peers_failed)1464 static void wlan_mlo_reset_ptqm_migrate_list(
1465 			struct wlan_mlo_dev_context *ml_dev,
1466 			struct peer_migrate_ptqm_multi_entries *list,
1467 			uint16_t num_peers_failed)
1468 {
1469 	struct peer_ptqm_migrate_list_entry *peer_entry, *next_entry;
1470 	uint16_t count = 0;
1471 
1472 	if (!ml_dev)
1473 		return;
1474 
1475 	peer_entry = mlo_ptqm_list_peek_head(&list->peer_list);
1476 	while (peer_entry) {
1477 		/* Reset the flags only for entries for which wmi
1478 		 * command trigger is failed
1479 		 */
1480 		if (count < list->num_entries - num_peers_failed) {
1481 			count++;
1482 			next_entry = mlo_get_next_peer_ctx(&list->peer_list,
1483 							   peer_entry);
1484 			peer_entry = next_entry;
1485 			continue;
1486 		}
1487 		if (peer_entry->peer) {
1488 			qdf_clear_bit(peer_entry->mlo_peer_id, ml_dev->mlo_peer_id_bmap);
1489 			peer_entry->peer->mlo_peer_ctx->primary_umac_migration_in_progress = false;
1490 			peer_entry->peer->mlo_peer_ctx->migrate_primary_umac_psoc_id =
1491 							ML_PRIMARY_UMAC_ID_INVAL;
1492 		}
1493 		next_entry = mlo_get_next_peer_ctx(&list->peer_list,
1494 						   peer_entry);
1495 		peer_entry = next_entry;
1496 	}
1497 }
1498 
1499 /**
1500  * wlan_mlo_build_ptqm_migrate_list() - API to build peer ptqm migration list
1501  * @vdev: objmgr vdev list
1502  * @object: peer object
1503  * @arg: list pointer
1504  *
1505  * API to build peer ptqm migration list
1506  *
1507  * Return: void
1508  */
wlan_mlo_build_ptqm_migrate_list(struct wlan_objmgr_vdev * vdev,void * object,void * arg)1509 static void wlan_mlo_build_ptqm_migrate_list(struct wlan_objmgr_vdev *vdev,
1510 					     void *object, void *arg)
1511 {
1512 	struct wlan_objmgr_peer *peer = (struct wlan_objmgr_peer *)object;
1513 	struct peer_migrate_ptqm_multi_entries *list =
1514 				(struct peer_migrate_ptqm_multi_entries *)arg;
1515 	struct peer_ptqm_migrate_list_entry *peer_entry;
1516 	struct wlan_mlo_peer_context *ml_peer;
1517 	uint16_t new_hw_link_id = INVALID_HW_LINK_ID;
1518 	uint8_t current_primary_link_id = WLAN_LINK_ID_INVALID;
1519 	QDF_STATUS status;
1520 
1521 	if (!wlan_peer_is_mlo(peer) || !peer->mlo_peer_ctx)
1522 		return;
1523 
1524 	ml_peer = peer->mlo_peer_ctx;
1525 
1526 	if (ml_peer->link_peer_cnt == 1)
1527 		return;
1528 
1529 	if (ml_peer->primary_umac_migration_in_progress) {
1530 		mlo_err("peer " QDF_MAC_ADDR_FMT " primary umac migration already in progress",
1531 			QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes));
1532 		return;
1533 	}
1534 
1535 	current_primary_link_id = wlan_mlo_peer_get_primary_peer_link_id_by_ml_peer(ml_peer);
1536 	if (current_primary_link_id == WLAN_LINK_ID_INVALID ||
1537 	    current_primary_link_id != wlan_vdev_get_link_id(vdev)) {
1538 		mlo_debug("peer " QDF_MAC_ADDR_FMT " not having primary on current vdev",
1539 			  QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes));
1540 		return;
1541 	}
1542 
1543 	status = wlan_mlo_get_new_ptqm_id(vdev, ml_peer,
1544 					  WLAN_LINK_ID_INVALID,
1545 					  &new_hw_link_id, true);
1546 	if (QDF_IS_STATUS_ERROR(status)) {
1547 		mlo_err("peer " QDF_MAC_ADDR_FMT " unable to get new ptqm id",
1548 			QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes));
1549 		return;
1550 	}
1551 	ml_peer->primary_umac_migration_in_progress = true;
1552 
1553 	peer_entry = (struct peer_ptqm_migrate_list_entry *)
1554 			qdf_mem_malloc(sizeof(struct peer_ptqm_migrate_list_entry));
1555 	if (!peer_entry) {
1556 		mlo_err("peer " QDF_MAC_ADDR_FMT " unable to allocate peer entry",
1557 			QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes));
1558 		return;
1559 	}
1560 
1561 	status = wlan_objmgr_peer_try_get_ref(peer, WLAN_MLME_SB_ID);
1562 	peer_entry->peer = peer;
1563 	peer_entry->new_hw_link_id = new_hw_link_id;
1564 	peer_entry->mlo_peer_id = ml_peer->mlo_peer_id;
1565 	qdf_list_insert_back(&list->peer_list, &peer_entry->node);
1566 	list->num_entries++;
1567 }
1568 
1569 /**
1570  * wlan_mlo_trigger_link_ptqm_migration() - API to trigger ptqm migration
1571  * for a link
1572  * @vdev: objmgr vdev object
1573  *
1574  * API to trigger ptqm migration of all peers having primary on given link
1575  *
1576  * Return: QDF_STATUS
1577  */
wlan_mlo_trigger_link_ptqm_migration(struct wlan_objmgr_vdev * vdev)1578 static QDF_STATUS wlan_mlo_trigger_link_ptqm_migration(
1579 				struct wlan_objmgr_vdev *vdev)
1580 {
1581 	struct peer_migrate_ptqm_multi_entries migrate_list = {0};
1582 	QDF_STATUS status;
1583 	uint16_t num_peers_failed = 0;
1584 
1585 	qdf_list_create(&migrate_list.peer_list, MAX_MLO_PEER_ID);
1586 	wlan_objmgr_iterate_peerobj_list(vdev,
1587 					 wlan_mlo_build_ptqm_migrate_list,
1588 					 &migrate_list, WLAN_MLME_NB_ID);
1589 
1590 	/* trigger WMI */
1591 	if (migrate_list.num_entries == 0) {
1592 		mlo_err("No peer found");
1593 		return QDF_STATUS_SUCCESS;
1594 	}
1595 
1596 	status = wlan_mlo_send_ptqm_migrate_cmd(vdev, &migrate_list,
1597 						&num_peers_failed);
1598 	if (QDF_IS_STATUS_ERROR(status))
1599 		wlan_mlo_reset_ptqm_migrate_list(vdev->mlo_dev_ctx,
1600 						 &migrate_list,
1601 						 num_peers_failed);
1602 	wlan_mlo_free_ptqm_migrate_list(&migrate_list);
1603 	return status;
1604 }
1605 
wlan_mlo_set_ptqm_migration(struct wlan_objmgr_vdev * vdev,struct wlan_mlo_peer_context * ml_peer,bool link_migration,uint32_t link_id,bool force_mig)1606 QDF_STATUS wlan_mlo_set_ptqm_migration(struct wlan_objmgr_vdev *vdev,
1607 				       struct wlan_mlo_peer_context *ml_peer,
1608 				       bool link_migration,
1609 				       uint32_t link_id, bool force_mig)
1610 {
1611 	uint16_t new_hw_link_id = INVALID_HW_LINK_ID;
1612 	struct peer_migrate_ptqm_multi_entries migrate_list = {0};
1613 	struct peer_ptqm_migrate_list_entry *peer_entry;
1614 	struct wlan_objmgr_vdev *curr_vdev = NULL;
1615 	uint8_t current_primary_link_id = WLAN_LINK_ID_INVALID;
1616 	uint16_t num_peers_failed = 0;
1617 	QDF_STATUS status;
1618 
1619 	if (!vdev) {
1620 		mlo_err("Vdev is NULL");
1621 		return QDF_STATUS_E_NULL_VALUE;
1622 	}
1623 
1624 	if (link_migration == false && !ml_peer) {
1625 		mlo_err("ML peer is NULL");
1626 		return QDF_STATUS_E_NULL_VALUE;
1627 	}
1628 
1629 	if (link_migration) {
1630 		mlo_info("Trigger migration for full link");
1631 		// trigger full link migration
1632 		status = wlan_mlo_trigger_link_ptqm_migration(vdev);
1633 		if (QDF_IS_STATUS_ERROR(status))
1634 			mlo_err("Failed to trigger link migration");
1635 		return status;
1636 	}
1637 
1638 	if (ml_peer->link_peer_cnt == 1) {
1639 		mlo_info("peer " QDF_MAC_ADDR_FMT " is SLO",
1640 			 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes));
1641 		return QDF_STATUS_E_FAILURE;
1642 	}
1643 
1644 	if (ml_peer->primary_umac_migration_in_progress) {
1645 		mlo_info("peer " QDF_MAC_ADDR_FMT " primary umac migration already in progress",
1646 			 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes));
1647 		return QDF_STATUS_E_FAILURE;
1648 	}
1649 
1650 	current_primary_link_id = wlan_mlo_peer_get_primary_peer_link_id_by_ml_peer(ml_peer);
1651 	if (current_primary_link_id == WLAN_LINK_ID_INVALID) {
1652 		mlo_err("Current primary link id is invalid");
1653 		return QDF_STATUS_E_FAILURE;
1654 	}
1655 
1656 	curr_vdev = mlo_get_vdev_by_link_id(vdev, current_primary_link_id,
1657 					    WLAN_MLO_MGR_ID);
1658 	if (!curr_vdev) {
1659 		mlo_err("Unable to get current primary vdev");
1660 		return QDF_STATUS_E_NULL_VALUE;
1661 	}
1662 
1663 	status = wlan_mlo_get_new_ptqm_id(curr_vdev, ml_peer,
1664 					  link_id, &new_hw_link_id, force_mig);
1665 	if (QDF_IS_STATUS_ERROR(status)) {
1666 		mlo_err("peer " QDF_MAC_ADDR_FMT " unable to get new ptqm id",
1667 			QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes));
1668 		goto exit;
1669 	}
1670 	ml_peer->primary_umac_migration_in_progress = true;
1671 
1672 	peer_entry = (struct peer_ptqm_migrate_list_entry *)
1673 				qdf_mem_malloc(sizeof(struct peer_ptqm_migrate_list_entry));
1674 	if (!peer_entry) {
1675 		mlo_err("Failed to allocate peer entry");
1676 		status = QDF_STATUS_E_NULL_VALUE;
1677 		goto exit;
1678 	}
1679 
1680 	peer_entry->new_hw_link_id = new_hw_link_id;
1681 	peer_entry->mlo_peer_id = ml_peer->mlo_peer_id;
1682 	qdf_list_create(&migrate_list.peer_list, MAX_MLO_PEER_ID);
1683 	qdf_list_insert_back(&migrate_list.peer_list, &peer_entry->node);
1684 	migrate_list.num_entries = 1;
1685 
1686 	//trigger WMI
1687 	status = wlan_mlo_send_ptqm_migrate_cmd(curr_vdev, &migrate_list,
1688 						&num_peers_failed);
1689 	if (QDF_IS_STATUS_ERROR(status))
1690 		wlan_mlo_reset_ptqm_migrate_list(curr_vdev->mlo_dev_ctx,
1691 						 &migrate_list,
1692 						 num_peers_failed);
1693 	wlan_mlo_free_ptqm_migrate_list(&migrate_list);
1694 
1695 exit:
1696 	if (curr_vdev)
1697 		mlo_release_vdev_ref(curr_vdev);
1698 
1699 	return status;
1700 }
1701 #endif /* QCA_SUPPORT_PRIMARY_LINK_MIGRATE */
1702