xref: /wlan-dirver/qca-wifi-host-cmn/umac/mlo_mgr/src/wlan_mlo_mgr_primary_umac.c (revision c7eaf5ac989ac229214b8317faa3e981d261e7db)
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 
27 /**
28  * struct mlpeer_data: PSOC peers MLO data
29  * @total_rssi:  sum of RSSI of all ML peers
30  * @num_ml_peers: Number of ML peer's with this PSOC as TQM
31  * @max_ml_peers: Max ML peers can have this PSOC as TQM
32  *                (it is to distribute peers across all PSOCs)
33  * @num_non_ml_peers: Non MLO peers of this PSOC
34  */
35 struct mlpeer_data {
36 	int32_t total_rssi;
37 	uint16_t num_ml_peers;
38 	uint16_t max_ml_peers;
39 	uint16_t num_non_ml_peers;
40 };
41 
42 /**
43  * struct mlo_all_link_rssi: structure to collect TQM params for all PSOCs
44  * @psoc_tqm_parms:  It collects peer data for all PSOCs
45  * @num_psocs:       Number of PSOCs in the system
46  * @current_psoc_id: current psoc id, it is for iterator
47  */
48 struct mlo_all_link_rssi {
49 	struct mlpeer_data psoc_tqm_parms[WLAN_OBJMGR_MAX_DEVICES];
50 	uint8_t num_psocs;
51 	uint8_t current_psoc_id;
52 };
53 
54 /* Invalid TQM/PSOC ID */
55 #define ML_INVALID_PRIMARY_TQM   0xff
56 /* Congestion value */
57 #define ML_PRIMARY_TQM_CONGESTION 30
58 
59 static void wlan_mlo_peer_get_rssi(struct wlan_objmgr_psoc *psoc,
60 				   void *obj, void *args)
61 {
62 	struct wlan_mlo_peer_context *mlo_peer_ctx;
63 	struct wlan_objmgr_peer *peer = (struct wlan_objmgr_peer *)obj;
64 	struct mlo_all_link_rssi *rssi_data = (struct mlo_all_link_rssi *)args;
65 	struct mlpeer_data *tqm_params = NULL;
66 	uint8_t index;
67 
68 	mlo_peer_ctx = peer->mlo_peer_ctx;
69 	index = rssi_data->current_psoc_id;
70 	tqm_params = &rssi_data->psoc_tqm_parms[index];
71 
72 	if (!wlan_peer_is_mlo(peer) && !mlo_peer_ctx) {
73 		if (wlan_peer_get_peer_type(peer) == WLAN_PEER_STA)
74 			tqm_params->num_non_ml_peers += 1;
75 		return;
76 	}
77 
78 	if (!mlo_peer_ctx)
79 		return;
80 
81 	/* If this psoc is not primary UMAC, don't account RSSI */
82 	if (mlo_peer_ctx->primary_umac_psoc_id != rssi_data->current_psoc_id)
83 		return;
84 
85 	tqm_params->total_rssi += mlo_peer_ctx->avg_link_rssi;
86 	tqm_params->num_ml_peers += 1;
87 }
88 
89 static void wlan_get_rssi_data_each_psoc(struct wlan_objmgr_psoc *psoc,
90 					 void *arg, uint8_t index)
91 {
92 	struct mlo_all_link_rssi *rssi_data = (struct mlo_all_link_rssi *)arg;
93 	struct mlpeer_data *tqm_params = NULL;
94 
95 	tqm_params = &rssi_data->psoc_tqm_parms[index];
96 
97 	tqm_params->total_rssi = 0;
98 	tqm_params->num_ml_peers = 0;
99 	tqm_params->num_non_ml_peers = 0;
100 	tqm_params->max_ml_peers = MAX_MLO_PEER;
101 
102 	rssi_data->current_psoc_id = index;
103 	rssi_data->num_psocs++;
104 
105 	wlan_objmgr_iterate_obj_list(psoc, WLAN_PEER_OP,
106 				     wlan_mlo_peer_get_rssi, rssi_data, 0,
107 				     WLAN_MLO_MGR_ID);
108 }
109 
110 static QDF_STATUS mld_get_link_rssi(struct mlo_all_link_rssi *rssi_data)
111 {
112 	rssi_data->num_psocs = 0;
113 
114 	wlan_objmgr_iterate_psoc_list(wlan_get_rssi_data_each_psoc,
115 				      rssi_data, WLAN_MLO_MGR_ID);
116 
117 	return QDF_STATUS_SUCCESS;
118 }
119 
120 static void
121 mld_get_best_primary_umac_w_rssi(struct wlan_mlo_peer_context *ml_peer,
122 				 struct wlan_objmgr_vdev *link_vdevs[])
123 {
124 	struct mlo_all_link_rssi rssi_data;
125 	uint8_t i;
126 	int32_t avg_rssi[WLAN_OBJMGR_MAX_DEVICES] = {0};
127 	int32_t diff_rssi[WLAN_OBJMGR_MAX_DEVICES] = {0};
128 	int32_t diff_low;
129 	bool mld_sta_links[WLAN_OBJMGR_MAX_DEVICES] = {0};
130 	bool mld_no_sta[WLAN_OBJMGR_MAX_DEVICES] = {0};
131 	struct wlan_objmgr_peer *assoc_peer = NULL;
132 	uint8_t prim_link, id;
133 	uint8_t num_psocs;
134 	struct mlpeer_data *tqm_params = NULL;
135 	struct wlan_channel *channel;
136 	enum phy_ch_width chwidth;
137 	uint8_t cong = ML_PRIMARY_TQM_CONGESTION;
138 	uint16_t mld_ml_sta_count[WLAN_OBJMGR_MAX_DEVICES] = {0};
139 	enum phy_ch_width mld_ch_width[WLAN_OBJMGR_MAX_DEVICES];
140 	uint8_t psoc_w_nosta;
141 	uint16_t ml_sta_count = 0;
142 	uint32_t total_cap, cap;
143 	uint16_t bw;
144 	bool group_full[WLAN_OBJMGR_MAX_DEVICES] = {0};
145 	uint16_t group_size[WLAN_OBJMGR_MAX_DEVICES] = {0};
146 	uint16_t grp_size = 0;
147 	uint16_t group_full_count = 0;
148 
149 	mld_get_link_rssi(&rssi_data);
150 
151 	for (i = 0; i < rssi_data.num_psocs; i++) {
152 		tqm_params = &rssi_data.psoc_tqm_parms[i];
153 
154 		if (tqm_params->num_ml_peers)
155 			avg_rssi[i] = (tqm_params->total_rssi /
156 				       tqm_params->num_ml_peers);
157 	}
158 
159 	/**
160 	 * If MLD STA associated to a set of links, choose primary UMAC
161 	 * from those links only
162 	 */
163 	num_psocs = 0;
164 	psoc_w_nosta = 0;
165 	for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++)
166 		mld_ch_width[i] = CH_WIDTH_INVALID;
167 
168 	for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
169 		if (!link_vdevs[i])
170 			continue;
171 
172 		id = wlan_vdev_get_psoc_id(link_vdevs[i]);
173 		if (id >= WLAN_OBJMGR_MAX_DEVICES)
174 			continue;
175 
176 		if (wlan_vdev_skip_pumac(link_vdevs[i])) {
177 			mlo_err("Skip Radio for Primary MLO umac");
178 			mld_sta_links[id] = false;
179 			continue;
180 		}
181 
182 		tqm_params = &rssi_data.psoc_tqm_parms[id];
183 		mld_sta_links[id] = true;
184 
185 		channel = wlan_vdev_mlme_get_bss_chan(link_vdevs[i]);
186 		mld_ch_width[id] = channel->ch_width;
187 
188 		if ((tqm_params->num_ml_peers +
189 		     tqm_params->num_non_ml_peers) == 0) {
190 			/* If this PSOC has no stations */
191 			mld_no_sta[id] = true;
192 			psoc_w_nosta++;
193 		}
194 
195 		mld_ml_sta_count[id] = tqm_params->num_ml_peers;
196 		/* Update total MLO STA count */
197 		ml_sta_count += tqm_params->num_ml_peers;
198 
199 		num_psocs++;
200 
201 		/* If no stations are associated, derive diff rssi
202 		 * based on psoc id {0-20, 20-40, 40 } so that
203 		 * stations are distributed across TQMs
204 		 */
205 		if (!avg_rssi[id]) {
206 			diff_rssi[id] = (id * 20);
207 			continue;
208 		}
209 		diff_rssi[id] = (ml_peer->avg_link_rssi >= avg_rssi[id]) ?
210 				(ml_peer->avg_link_rssi - avg_rssi[id]) :
211 				(avg_rssi[id] - ml_peer->avg_link_rssi);
212 
213 	}
214 
215 	prim_link = ML_INVALID_PRIMARY_TQM;
216 
217 	/* If one of the PSOCs doesn't have any station select that PSOC as
218 	 * primary TQM. If more than one PSOC have no stations as Primary TQM
219 	 * the vdev with less bw needs to be selected as Primary TQM
220 	 */
221 	if (psoc_w_nosta == 1) {
222 		for (i = 0; i < WLAN_OBJMGR_MAX_DEVICES; i++) {
223 			if (mld_no_sta[i]) {
224 				prim_link = i;
225 				break;
226 			}
227 		}
228 	} else if (psoc_w_nosta > 1) {
229 		chwidth = CH_WIDTH_INVALID;
230 		for (i = 0; i < WLAN_OBJMGR_MAX_DEVICES; i++) {
231 			if (!mld_no_sta[i])
232 				continue;
233 
234 			if (chwidth == CH_WIDTH_INVALID) {
235 				prim_link = i;
236 				chwidth = mld_ch_width[i];
237 				continue;
238 			}
239 
240 			/* If bw is less than or equal to 160 MHZ
241 			 * and chwidth is less than other link
242 			 * Mark this link as primary link
243 			 */
244 			if ((mld_ch_width[i] <= CH_WIDTH_160MHZ) &&
245 			    (chwidth > mld_ch_width[i])) {
246 				prim_link = i;
247 				chwidth = mld_ch_width[i];
248 			}
249 		}
250 	} else {
251 		total_cap = 0;
252 		for (i = 0; i < WLAN_OBJMGR_MAX_DEVICES; i++) {
253 			bw = wlan_reg_get_bw_value(mld_ch_width[i]);
254 			total_cap += bw * (100 - cong);
255 		}
256 
257 		group_full_count = 0;
258 		for (i = 0; i < WLAN_OBJMGR_MAX_DEVICES; i++) {
259 			if (!mld_sta_links[i])
260 				continue;
261 
262 			bw = wlan_reg_get_bw_value(mld_ch_width[i]);
263 			cap = bw * (100 - cong);
264 			grp_size = (ml_sta_count) * ((cap * 100) / total_cap);
265 			group_size[i] = grp_size / 100;
266 			if (group_size[i] <=  mld_ml_sta_count[i]) {
267 				group_full[i] = true;
268 				group_full_count++;
269 			}
270 		}
271 
272 		if ((num_psocs - group_full_count) == 1) {
273 			for (i = 0; i < WLAN_OBJMGR_MAX_DEVICES; i++) {
274 				if (!mld_sta_links[i])
275 					continue;
276 
277 				if (group_full[i])
278 					continue;
279 
280 				prim_link = i;
281 				break;
282 			}
283 		} else {
284 			diff_low = 0;
285 			/* find min diff, based on it, allocate primary umac */
286 			for (i = 0; i < WLAN_OBJMGR_MAX_DEVICES; i++) {
287 				if (!mld_sta_links[i])
288 					continue;
289 
290 				/* First iteration */
291 				if (diff_low == 0) {
292 					diff_low = diff_rssi[i];
293 					prim_link = i;
294 				} else if (diff_low > diff_rssi[i]) {
295 					diff_low = diff_rssi[i];
296 					prim_link = i;
297 				}
298 			}
299 		}
300 	}
301 
302 	if (prim_link != ML_INVALID_PRIMARY_TQM) {
303 		ml_peer->primary_umac_psoc_id = prim_link;
304 	} else {
305 		assoc_peer = wlan_mlo_peer_get_assoc_peer(ml_peer);
306 		if (!assoc_peer) {
307 			mlo_err(QDF_MAC_ADDR_FMT ":Assoc peer is NULL",
308 				QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes));
309 			QDF_BUG(0);
310 			return;
311 		}
312 		ml_peer->primary_umac_psoc_id =
313 			wlan_peer_get_psoc_id(assoc_peer);
314 	}
315 }
316 
317 void mlo_peer_assign_primary_umac(
318 		struct wlan_mlo_peer_context *ml_peer,
319 		struct wlan_mlo_link_peer_entry *peer_entry)
320 {
321 	struct wlan_mlo_link_peer_entry *peer_ent_iter;
322 	uint8_t i;
323 	uint8_t primary_umac_set = 0;
324 
325 	/* If MLD is within single SOC, then assoc link becomes
326 	 * primary umac
327 	 */
328 	if (ml_peer->primary_umac_psoc_id == ML_PRIMARY_UMAC_ID_INVAL) {
329 		if (wlan_peer_mlme_is_assoc_peer(peer_entry->link_peer)) {
330 			peer_entry->is_primary = true;
331 			ml_peer->primary_umac_psoc_id =
332 				wlan_peer_get_psoc_id(peer_entry->link_peer);
333 		} else {
334 			peer_entry->is_primary = false;
335 		}
336 	} else {
337 		/* If this peer PSOC is not derived as Primary PSOC,
338 		 * mark is_primary as false
339 		 */
340 		if (wlan_peer_get_psoc_id(peer_entry->link_peer) !=
341 				ml_peer->primary_umac_psoc_id) {
342 			peer_entry->is_primary = false;
343 			return;
344 		}
345 
346 		/* For single SOC, check whether is_primary is set for
347 		 * other partner peer, then mark is_primary false for this peer
348 		 */
349 		for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
350 			peer_ent_iter = &ml_peer->peer_list[i];
351 
352 			if (!peer_ent_iter->link_peer)
353 				continue;
354 
355 			/* Check for other link peers */
356 			if (peer_ent_iter == peer_entry)
357 				continue;
358 
359 			if (wlan_peer_get_psoc_id(peer_ent_iter->link_peer) !=
360 					ml_peer->primary_umac_psoc_id)
361 				continue;
362 
363 			if (peer_ent_iter->is_primary)
364 				primary_umac_set = 1;
365 		}
366 
367 		if (primary_umac_set)
368 			peer_entry->is_primary = false;
369 		else
370 			peer_entry->is_primary = true;
371 	}
372 }
373 
374 static int8_t wlan_vdev_derive_link_rssi(struct wlan_objmgr_vdev *vdev,
375 					 struct wlan_objmgr_vdev *assoc_vdev,
376 					 int8_t rssi)
377 {
378 	struct wlan_channel *channel, *assoc_channel;
379 	uint16_t ch_freq, assoc_freq;
380 	uint8_t tx_pow, assoc_tx_pow;
381 	int8_t diff_txpow;
382 	struct wlan_objmgr_pdev *pdev, *assoc_pdev;
383 	uint8_t log10_freq;
384 	uint8_t derived_rssi;
385 	int16_t ten_derived_rssi;
386 	int8_t ten_diff_pl = 0;
387 
388 	pdev = wlan_vdev_get_pdev(vdev);
389 	assoc_pdev = wlan_vdev_get_pdev(assoc_vdev);
390 
391 	channel = wlan_vdev_get_active_channel(vdev);
392 	if (channel)
393 		ch_freq = channel->ch_freq;
394 	else
395 		ch_freq = 1;
396 
397 	assoc_channel = wlan_vdev_get_active_channel(assoc_vdev);
398 	if (assoc_channel)
399 		assoc_freq = assoc_channel->ch_freq;
400 	else
401 		assoc_freq = 1;
402 
403 	/*
404 	 *  diff of path loss (of two links) = log10(freq1) - log10(freq2)
405 	 *                       (since distance is constant)
406 	 *  since log10 is not available, we cameup with approximate ranges
407 	 */
408 	log10_freq = (ch_freq * 10) / assoc_freq;
409 	if ((log10_freq >= 20) && (log10_freq < 30))
410 		ten_diff_pl = 4;  /* 0.4 *10 */
411 	else if ((log10_freq >= 11) && (log10_freq < 20))
412 		ten_diff_pl = 1;  /* 0.1 *10 */
413 	else if ((log10_freq >= 8) && (log10_freq < 11))
414 		ten_diff_pl = 0; /* 0 *10 */
415 	else if ((log10_freq >= 4) && (log10_freq < 8))
416 		ten_diff_pl = -1; /* -0.1 * 10 */
417 	else if ((log10_freq >= 1) && (log10_freq < 4))
418 		ten_diff_pl = -4;  /* -0.4 * 10 */
419 
420 	assoc_tx_pow = wlan_reg_get_channel_reg_power_for_freq(assoc_pdev,
421 							       assoc_freq);
422 	tx_pow = wlan_reg_get_channel_reg_power_for_freq(pdev, ch_freq);
423 
424 	diff_txpow = tx_pow -  assoc_tx_pow;
425 
426 	ten_derived_rssi = (diff_txpow * 10) - ten_diff_pl + (rssi * 10);
427 	derived_rssi = ten_derived_rssi / 10;
428 
429 	return derived_rssi;
430 }
431 
432 static void mlo_peer_calculate_avg_rssi(
433 		struct wlan_mlo_dev_context *ml_dev,
434 		struct wlan_mlo_peer_context *ml_peer,
435 		int8_t rssi,
436 		struct wlan_objmgr_vdev *assoc_vdev)
437 {
438 	int32_t total_rssi = 0;
439 	uint8_t num_psocs = 0;
440 	uint8_t i;
441 	struct wlan_objmgr_vdev *vdev;
442 
443 	for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
444 		vdev = ml_dev->wlan_vdev_list[i];
445 		if (!vdev)
446 			continue;
447 
448 		num_psocs++;
449 		if (vdev == assoc_vdev)
450 			total_rssi += rssi;
451 		else
452 			total_rssi += wlan_vdev_derive_link_rssi(vdev,
453 								 assoc_vdev,
454 								 rssi);
455 	}
456 
457 	if (!num_psocs)
458 		return;
459 
460 	ml_peer->avg_link_rssi = total_rssi / num_psocs;
461 }
462 
463 #ifdef WLAN_MLO_MULTI_CHIP
464 int8_t mlo_get_central_umac_id(
465 		uint8_t *psoc_ids)
466 {
467 	uint8_t prim_psoc_id = -1;
468 	uint8_t adjacent = 0;
469 
470 	/* Some 3 link RDPs have restriction on the primary umac.
471 	 * Only the link that is adjacent to both the links can be
472 	 * a primary umac.
473 	 * Note: it means umac migration is also restricted.
474 	 */
475 	mlo_chip_adjacent(psoc_ids[0], psoc_ids[1], &adjacent);
476 	if (!adjacent) {
477 		prim_psoc_id = psoc_ids[2];
478 	} else {
479 		mlo_chip_adjacent(psoc_ids[0], psoc_ids[2], &adjacent);
480 		if (!adjacent) {
481 			prim_psoc_id = psoc_ids[1];
482 		} else {
483 			/* If all links are adjacent to each other,
484 			 * no need to restrict the primary umac.
485 			 * return failure the caller will handle.
486 			 */
487 			mlo_chip_adjacent(psoc_ids[1], psoc_ids[2],
488 					  &adjacent);
489 			if (!adjacent)
490 				prim_psoc_id = psoc_ids[0];
491 			else
492 				return prim_psoc_id;
493 		}
494 	}
495 
496 	return prim_psoc_id;
497 }
498 
499 static QDF_STATUS mlo_set_3_link_primary_umac(
500 		struct wlan_mlo_peer_context *ml_peer,
501 		struct wlan_objmgr_vdev *link_vdevs[])
502 {
503 	uint8_t psoc_ids[WLAN_UMAC_MLO_MAX_VDEVS];
504 	int8_t central_umac_id;
505 
506 	if (ml_peer->max_links != 3)
507 		return QDF_STATUS_E_FAILURE;
508 
509 	/* Some 3 link RDPs have restriction on the primary umac.
510 	 * Only the link that is adjacent to both the links can be
511 	 * a primary umac.
512 	 * Note: it means umac migration is also restricted.
513 	 */
514 	psoc_ids[0] = wlan_vdev_get_psoc_id(link_vdevs[0]);
515 	psoc_ids[1] = wlan_vdev_get_psoc_id(link_vdevs[1]);
516 	psoc_ids[2] = wlan_vdev_get_psoc_id(link_vdevs[2]);
517 
518 	central_umac_id = mlo_get_central_umac_id(psoc_ids);
519 	if (central_umac_id != -1)
520 		ml_peer->primary_umac_psoc_id = central_umac_id;
521 	else
522 		return QDF_STATUS_E_FAILURE;
523 
524 	mlo_peer_assign_primary_umac(ml_peer,
525 				     &ml_peer->peer_list[0]);
526 
527 	return QDF_STATUS_SUCCESS;
528 }
529 #else
530 static QDF_STATUS mlo_set_3_link_primary_umac(
531 		struct wlan_mlo_peer_context *ml_peer,
532 		struct wlan_objmgr_vdev *link_vdevs[])
533 {
534 	return QDF_STATUS_E_FAILURE;
535 }
536 #endif
537 
538 #if defined(WLAN_FEATURE_11BE_MLO) && defined(WLAN_MLO_MULTI_CHIP)
539 QDF_STATUS mlo_peer_overwrite_primary_umac(uint8_t psoc_id,
540 					   struct wlan_mlo_peer_context *ml_peer)
541 {
542 	if (psoc_id >= WLAN_OBJMGR_MAX_DEVICES)
543 		return QDF_STATUS_E_FAILURE;
544 	if (!ml_peer)
545 		return QDF_STATUS_E_FAILURE;
546 
547 	ml_peer->primary_umac_psoc_id = psoc_id;
548 	mlo_peer_assign_primary_umac(ml_peer, &ml_peer->peer_list[0]);
549 
550 	return QDF_STATUS_SUCCESS;
551 }
552 #endif
553 
554 QDF_STATUS mlo_peer_allocate_primary_umac(
555 		struct wlan_mlo_dev_context *ml_dev,
556 		struct wlan_mlo_peer_context *ml_peer,
557 		struct wlan_objmgr_vdev *link_vdevs[])
558 {
559 	struct wlan_mlo_link_peer_entry *peer_entry;
560 	struct wlan_objmgr_peer *assoc_peer = NULL;
561 	int32_t rssi;
562 	struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx();
563 	uint8_t first_link_id = 0;
564 	bool primary_umac_set = false;
565 	uint8_t i, psoc_id;
566 
567 	peer_entry = &ml_peer->peer_list[0];
568 	assoc_peer = peer_entry->link_peer;
569 	if (!assoc_peer)
570 		return QDF_STATUS_E_FAILURE;
571 
572 	/* For Station mode, assign assoc peer as primary umac */
573 	if (wlan_peer_get_peer_type(assoc_peer) == WLAN_PEER_AP) {
574 		mlo_peer_assign_primary_umac(ml_peer, peer_entry);
575 		mlo_info("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " primary umac soc %d ",
576 			 ml_dev->mld_id,
577 			 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes),
578 			 ml_peer->primary_umac_psoc_id);
579 
580 		return QDF_STATUS_SUCCESS;
581 	}
582 
583 	/* Select assoc peer's PSOC as primary UMAC in Multi-chip solution,
584 	 * 1) for single link MLO connection
585 	 * 2) if MLD is single chip MLO
586 	 */
587 	if ((ml_peer->max_links == 1) ||
588 	    (mlo_vdevs_check_single_soc(link_vdevs, ml_peer->max_links))) {
589 		mlo_peer_assign_primary_umac(ml_peer, peer_entry);
590 		mlo_info("MLD ID %d Assoc peer " QDF_MAC_ADDR_FMT " primary umac soc %d ",
591 			 ml_dev->mld_id,
592 			 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes),
593 			 ml_peer->primary_umac_psoc_id);
594 
595 		return QDF_STATUS_SUCCESS;
596 	}
597 
598 	if (mlo_set_3_link_primary_umac(ml_peer, link_vdevs) ==
599 	    QDF_STATUS_SUCCESS) {
600 		/* If success then the primary umac is restricted and assigned.
601 		 * if not, there is no restriction, so just fallthrough
602 		 */
603 		mlo_info("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT
604 			 " center primary umac soc %d ",
605 			 ml_dev->mld_id,
606 			 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes),
607 			 ml_peer->primary_umac_psoc_id);
608 
609 		return QDF_STATUS_SUCCESS;
610 	}
611 
612 	if (mlo_ctx->mlo_is_force_primary_umac) {
613 		for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) {
614 			if (!link_vdevs[i])
615 				continue;
616 
617 			psoc_id = wlan_vdev_get_psoc_id(link_vdevs[i]);
618 			if (!first_link_id)
619 				first_link_id = psoc_id;
620 
621 			if (psoc_id == mlo_ctx->mlo_forced_primary_umac_id) {
622 				ml_peer->primary_umac_psoc_id = psoc_id;
623 				primary_umac_set = true;
624 				break;
625 			}
626 		}
627 
628 		if (!primary_umac_set)
629 			ml_peer->primary_umac_psoc_id = first_link_id;
630 
631 		mlo_peer_assign_primary_umac(ml_peer, peer_entry);
632 		mlo_info("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " primary umac soc %d ",
633 			 ml_dev->mld_id,
634 			 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes),
635 			 ml_peer->primary_umac_psoc_id);
636 
637 		return QDF_STATUS_SUCCESS;
638 	}
639 
640 	rssi = wlan_peer_get_rssi(assoc_peer);
641 	mlo_peer_calculate_avg_rssi(ml_dev, ml_peer, rssi,
642 				    wlan_peer_get_vdev(assoc_peer));
643 
644 	mld_get_best_primary_umac_w_rssi(ml_peer, link_vdevs);
645 
646 	mlo_peer_assign_primary_umac(ml_peer, peer_entry);
647 
648 	mlo_info("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " avg RSSI %d primary umac soc %d ",
649 		 ml_dev->mld_id,
650 		 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes),
651 		 ml_peer->avg_link_rssi, ml_peer->primary_umac_psoc_id);
652 
653 	return QDF_STATUS_SUCCESS;
654 }
655 
656 QDF_STATUS mlo_peer_free_primary_umac(
657 		struct wlan_mlo_dev_context *ml_dev,
658 		struct wlan_mlo_peer_context *ml_peer)
659 {
660 	return QDF_STATUS_SUCCESS;
661 }
662 
663 #ifdef QCA_SUPPORT_PRIMARY_LINK_MIGRATE
664 void wlan_objmgr_mlo_update_primary_info(struct wlan_objmgr_peer *peer)
665 {
666 	struct wlan_mlo_peer_context *ml_peer = NULL;
667 	struct wlan_mlo_link_peer_entry *peer_ent_iter;
668 	uint8_t i;
669 
670 	ml_peer = peer->mlo_peer_ctx;
671 	ml_peer->primary_umac_psoc_id = wlan_peer_get_psoc_id(peer);
672 
673 	for (i = 0; i < MAX_MLO_LINK_PEERS; i++) {
674 		peer_ent_iter = &ml_peer->peer_list[i];
675 
676 		if (!peer_ent_iter->link_peer)
677 			continue;
678 
679 		if (peer_ent_iter->is_primary)
680 			peer_ent_iter->is_primary = false;
681 
682 		if (peer_ent_iter->link_peer == peer)
683 			peer_ent_iter->is_primary = true;
684 	}
685 }
686 
687 qdf_export_symbol(wlan_objmgr_mlo_update_primary_info);
688 #endif
689