xref: /linux/drivers/net/wireless/intel/iwlwifi/mld/mlo.c (revision e8670620b07725d38f7c8a6f751a1173deeafb8a)
1 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
2 /*
3  * Copyright (C) 2024-2025 Intel Corporation
4  */
5 #include "mlo.h"
6 #include "phy.h"
7 
8 /* Block reasons helper */
9 #define HANDLE_EMLSR_BLOCKED_REASONS(HOW)	\
10 	HOW(PREVENTION)			\
11 	HOW(WOWLAN)			\
12 	HOW(FW)				\
13 	HOW(ROC)			\
14 	HOW(NON_BSS)			\
15 	HOW(TMP_NON_BSS)		\
16 	HOW(TPT)
17 
18 static const char *
19 iwl_mld_get_emlsr_blocked_string(enum iwl_mld_emlsr_blocked blocked)
20 {
21 	/* Using switch without "default" will warn about missing entries  */
22 	switch (blocked) {
23 #define REASON_CASE(x) case IWL_MLD_EMLSR_BLOCKED_##x: return #x;
24 	HANDLE_EMLSR_BLOCKED_REASONS(REASON_CASE)
25 #undef REASON_CASE
26 	}
27 
28 	return "ERROR";
29 }
30 
31 static void iwl_mld_print_emlsr_blocked(struct iwl_mld *mld, u32 mask)
32 {
33 #define NAME_FMT(x) "%s"
34 #define NAME_PR(x) (mask & IWL_MLD_EMLSR_BLOCKED_##x) ? "[" #x "]" : "",
35 	IWL_DEBUG_INFO(mld,
36 		       "EMLSR blocked = " HANDLE_EMLSR_BLOCKED_REASONS(NAME_FMT)
37 		       " (0x%x)\n",
38 		       HANDLE_EMLSR_BLOCKED_REASONS(NAME_PR)
39 		       mask);
40 #undef NAME_FMT
41 #undef NAME_PR
42 }
43 
44 /* Exit reasons helper */
45 #define HANDLE_EMLSR_EXIT_REASONS(HOW)	\
46 	HOW(BLOCK)			\
47 	HOW(MISSED_BEACON)		\
48 	HOW(FAIL_ENTRY)			\
49 	HOW(CSA)			\
50 	HOW(EQUAL_BAND)			\
51 	HOW(BANDWIDTH)			\
52 	HOW(LOW_RSSI)			\
53 	HOW(LINK_USAGE)			\
54 	HOW(BT_COEX)			\
55 	HOW(CHAN_LOAD)			\
56 	HOW(RFI)
57 
58 static const char *
59 iwl_mld_get_emlsr_exit_string(enum iwl_mld_emlsr_exit exit)
60 {
61 	/* Using switch without "default" will warn about missing entries  */
62 	switch (exit) {
63 #define REASON_CASE(x) case IWL_MLD_EMLSR_EXIT_##x: return #x;
64 	HANDLE_EMLSR_EXIT_REASONS(REASON_CASE)
65 #undef REASON_CASE
66 	}
67 
68 	return "ERROR";
69 }
70 
71 static void iwl_mld_print_emlsr_exit(struct iwl_mld *mld, u32 mask)
72 {
73 #define NAME_FMT(x) "%s"
74 #define NAME_PR(x) (mask & IWL_MLD_EMLSR_EXIT_##x) ? "[" #x "]" : "",
75 	IWL_DEBUG_INFO(mld,
76 		       "EMLSR exit = " HANDLE_EMLSR_EXIT_REASONS(NAME_FMT)
77 		       " (0x%x)\n",
78 		       HANDLE_EMLSR_EXIT_REASONS(NAME_PR)
79 		       mask);
80 #undef NAME_FMT
81 #undef NAME_PR
82 }
83 
84 void iwl_mld_emlsr_prevent_done_wk(struct wiphy *wiphy, struct wiphy_work *wk)
85 {
86 	struct iwl_mld_vif *mld_vif = container_of(wk, struct iwl_mld_vif,
87 						   emlsr.prevent_done_wk.work);
88 	struct ieee80211_vif *vif =
89 		container_of((void *)mld_vif, struct ieee80211_vif, drv_priv);
90 
91 	if (WARN_ON(!(mld_vif->emlsr.blocked_reasons &
92 		      IWL_MLD_EMLSR_BLOCKED_PREVENTION)))
93 		return;
94 
95 	iwl_mld_unblock_emlsr(mld_vif->mld, vif,
96 			      IWL_MLD_EMLSR_BLOCKED_PREVENTION);
97 }
98 
99 void iwl_mld_emlsr_tmp_non_bss_done_wk(struct wiphy *wiphy,
100 				       struct wiphy_work *wk)
101 {
102 	struct iwl_mld_vif *mld_vif = container_of(wk, struct iwl_mld_vif,
103 						   emlsr.prevent_done_wk.work);
104 	struct ieee80211_vif *vif =
105 		container_of((void *)mld_vif, struct ieee80211_vif, drv_priv);
106 
107 	if (WARN_ON(!(mld_vif->emlsr.blocked_reasons &
108 		      IWL_MLD_EMLSR_BLOCKED_TMP_NON_BSS)))
109 		return;
110 
111 	iwl_mld_unblock_emlsr(mld_vif->mld, vif,
112 			      IWL_MLD_EMLSR_BLOCKED_TMP_NON_BSS);
113 }
114 
115 #define IWL_MLD_TRIGGER_LINK_SEL_TIME	(HZ * IWL_MLD_TRIGGER_LINK_SEL_TIME_SEC)
116 #define IWL_MLD_SCAN_EXPIRE_TIME	(HZ * IWL_MLD_SCAN_EXPIRE_TIME_SEC)
117 
118 /* Exit reasons that can cause longer EMLSR prevention */
119 #define IWL_MLD_PREVENT_EMLSR_REASONS	(IWL_MLD_EMLSR_EXIT_MISSED_BEACON | \
120 					 IWL_MLD_EMLSR_EXIT_LINK_USAGE)
121 #define IWL_MLD_PREVENT_EMLSR_TIMEOUT	(HZ * 400)
122 
123 #define IWL_MLD_EMLSR_PREVENT_SHORT	(HZ * 300)
124 #define IWL_MLD_EMLSR_PREVENT_LONG	(HZ * 600)
125 
126 static void iwl_mld_check_emlsr_prevention(struct iwl_mld *mld,
127 					   struct iwl_mld_vif *mld_vif,
128 					   enum iwl_mld_emlsr_exit reason)
129 {
130 	unsigned long delay;
131 
132 	/*
133 	 * Reset the counter if more than 400 seconds have passed between one
134 	 * exit and the other, or if we exited due to a different reason.
135 	 * Will also reset the counter after the long prevention is done.
136 	 */
137 	if (time_after(jiffies, mld_vif->emlsr.last_exit_ts +
138 				IWL_MLD_PREVENT_EMLSR_TIMEOUT) ||
139 	    mld_vif->emlsr.last_exit_reason != reason)
140 		mld_vif->emlsr.exit_repeat_count = 0;
141 
142 	mld_vif->emlsr.last_exit_reason = reason;
143 	mld_vif->emlsr.last_exit_ts = jiffies;
144 	mld_vif->emlsr.exit_repeat_count++;
145 
146 	/*
147 	 * Do not add a prevention when the reason was a block. For a block,
148 	 * EMLSR will be enabled again on unblock.
149 	 */
150 	if (reason == IWL_MLD_EMLSR_EXIT_BLOCK)
151 		return;
152 
153 	/* Set prevention for a minimum of 30 seconds */
154 	mld_vif->emlsr.blocked_reasons |= IWL_MLD_EMLSR_BLOCKED_PREVENTION;
155 	delay = IWL_MLD_TRIGGER_LINK_SEL_TIME;
156 
157 	/* Handle repeats for reasons that can cause long prevention */
158 	if (mld_vif->emlsr.exit_repeat_count > 1 &&
159 	    reason & IWL_MLD_PREVENT_EMLSR_REASONS) {
160 		if (mld_vif->emlsr.exit_repeat_count == 2)
161 			delay = IWL_MLD_EMLSR_PREVENT_SHORT;
162 		else
163 			delay = IWL_MLD_EMLSR_PREVENT_LONG;
164 
165 		/*
166 		 * The timeouts are chosen so that this will not happen, i.e.
167 		 * IWL_MLD_EMLSR_PREVENT_LONG > IWL_MLD_PREVENT_EMLSR_TIMEOUT
168 		 */
169 		WARN_ON(mld_vif->emlsr.exit_repeat_count > 3);
170 	}
171 
172 	IWL_DEBUG_INFO(mld,
173 		       "Preventing EMLSR for %ld seconds due to %u exits with the reason = %s (0x%x)\n",
174 		       delay / HZ, mld_vif->emlsr.exit_repeat_count,
175 		       iwl_mld_get_emlsr_exit_string(reason), reason);
176 
177 	wiphy_delayed_work_queue(mld->wiphy,
178 				 &mld_vif->emlsr.prevent_done_wk, delay);
179 }
180 
181 static void iwl_mld_clear_avg_chan_load_iter(struct ieee80211_hw *hw,
182 					     struct ieee80211_chanctx_conf *ctx,
183 					     void *dat)
184 {
185 	struct iwl_mld_phy *phy = iwl_mld_phy_from_mac80211(ctx);
186 
187 	/* It is ok to do it for all chanctx (and not only for the ones that
188 	 * belong to the EMLSR vif) since EMLSR is not allowed if there is
189 	 * another vif.
190 	 */
191 	phy->avg_channel_load_not_by_us = 0;
192 }
193 
194 static int _iwl_mld_exit_emlsr(struct iwl_mld *mld, struct ieee80211_vif *vif,
195 			       enum iwl_mld_emlsr_exit exit, u8 link_to_keep,
196 			       bool sync)
197 {
198 	struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);
199 	u16 new_active_links;
200 	int ret = 0;
201 
202 	lockdep_assert_wiphy(mld->wiphy);
203 
204 	/* On entry failure need to exit anyway, even if entered from debugfs */
205 	if (exit != IWL_MLD_EMLSR_EXIT_FAIL_ENTRY && !IWL_MLD_AUTO_EML_ENABLE)
206 		return 0;
207 
208 	/* Ignore exit request if EMLSR is not active */
209 	if (!iwl_mld_emlsr_active(vif))
210 		return 0;
211 
212 	if (WARN_ON(!ieee80211_vif_is_mld(vif) || !mld_vif->authorized))
213 		return 0;
214 
215 	if (WARN_ON(!(vif->active_links & BIT(link_to_keep))))
216 		link_to_keep = __ffs(vif->active_links);
217 
218 	new_active_links = BIT(link_to_keep);
219 	IWL_DEBUG_INFO(mld,
220 		       "Exiting EMLSR. reason = %s (0x%x). Current active links=0x%x, new active links = 0x%x\n",
221 		       iwl_mld_get_emlsr_exit_string(exit), exit,
222 		       vif->active_links, new_active_links);
223 
224 	if (sync)
225 		ret = ieee80211_set_active_links(vif, new_active_links);
226 	else
227 		ieee80211_set_active_links_async(vif, new_active_links);
228 
229 	/* Update latest exit reason and check EMLSR prevention */
230 	iwl_mld_check_emlsr_prevention(mld, mld_vif, exit);
231 
232 	/* channel_load_not_by_us is invalid when in EMLSR.
233 	 * Clear it so wrong values won't be used.
234 	 */
235 	ieee80211_iter_chan_contexts_atomic(mld->hw,
236 					    iwl_mld_clear_avg_chan_load_iter,
237 					    NULL);
238 
239 	return ret;
240 }
241 
242 void iwl_mld_exit_emlsr(struct iwl_mld *mld, struct ieee80211_vif *vif,
243 			enum iwl_mld_emlsr_exit exit, u8 link_to_keep)
244 {
245 	_iwl_mld_exit_emlsr(mld, vif, exit, link_to_keep, false);
246 }
247 
248 static int _iwl_mld_emlsr_block(struct iwl_mld *mld, struct ieee80211_vif *vif,
249 				enum iwl_mld_emlsr_blocked reason,
250 				u8 link_to_keep, bool sync)
251 {
252 	struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);
253 
254 	lockdep_assert_wiphy(mld->wiphy);
255 
256 	if (!IWL_MLD_AUTO_EML_ENABLE || !iwl_mld_vif_has_emlsr_cap(vif))
257 		return 0;
258 
259 	if (mld_vif->emlsr.blocked_reasons & reason)
260 		return 0;
261 
262 	mld_vif->emlsr.blocked_reasons |= reason;
263 
264 	IWL_DEBUG_INFO(mld,
265 		       "Blocking EMLSR mode. reason = %s (0x%x)\n",
266 		       iwl_mld_get_emlsr_blocked_string(reason), reason);
267 	iwl_mld_print_emlsr_blocked(mld, mld_vif->emlsr.blocked_reasons);
268 
269 	if (reason == IWL_MLD_EMLSR_BLOCKED_TPT)
270 		wiphy_delayed_work_cancel(mld_vif->mld->wiphy,
271 					  &mld_vif->emlsr.check_tpt_wk);
272 
273 	return _iwl_mld_exit_emlsr(mld, vif, IWL_MLD_EMLSR_EXIT_BLOCK,
274 				   link_to_keep, sync);
275 }
276 
277 void iwl_mld_block_emlsr(struct iwl_mld *mld, struct ieee80211_vif *vif,
278 			 enum iwl_mld_emlsr_blocked reason, u8 link_to_keep)
279 {
280 	_iwl_mld_emlsr_block(mld, vif, reason, link_to_keep, false);
281 }
282 
283 int iwl_mld_block_emlsr_sync(struct iwl_mld *mld, struct ieee80211_vif *vif,
284 			     enum iwl_mld_emlsr_blocked reason, u8 link_to_keep)
285 {
286 	return _iwl_mld_emlsr_block(mld, vif, reason, link_to_keep, true);
287 }
288 
289 static void _iwl_mld_select_links(struct iwl_mld *mld,
290 				  struct ieee80211_vif *vif);
291 
292 void iwl_mld_trigger_link_selection(struct iwl_mld *mld,
293 				    struct ieee80211_vif *vif)
294 {
295 	bool last_scan_was_recent =
296 		time_before(jiffies, mld->scan.last_mlo_scan_jiffies +
297 				     IWL_MLD_SCAN_EXPIRE_TIME);
298 
299 	if (last_scan_was_recent) {
300 		IWL_DEBUG_EHT(mld, "MLO scan was recent, skip.\n");
301 		_iwl_mld_select_links(mld, vif);
302 	} else {
303 		IWL_DEBUG_EHT(mld, "Doing link selection after MLO scan\n");
304 		iwl_mld_int_mlo_scan(mld, vif);
305 	}
306 }
307 
308 void iwl_mld_unblock_emlsr(struct iwl_mld *mld, struct ieee80211_vif *vif,
309 			   enum iwl_mld_emlsr_blocked reason)
310 {
311 	struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);
312 
313 	lockdep_assert_wiphy(mld->wiphy);
314 
315 	if (!IWL_MLD_AUTO_EML_ENABLE || !iwl_mld_vif_has_emlsr_cap(vif))
316 		return;
317 
318 	if (!(mld_vif->emlsr.blocked_reasons & reason))
319 		return;
320 
321 	mld_vif->emlsr.blocked_reasons &= ~reason;
322 
323 	IWL_DEBUG_INFO(mld,
324 		       "Unblocking EMLSR mode. reason = %s (0x%x)\n",
325 		       iwl_mld_get_emlsr_blocked_string(reason), reason);
326 	iwl_mld_print_emlsr_blocked(mld, mld_vif->emlsr.blocked_reasons);
327 
328 	if (reason == IWL_MLD_EMLSR_BLOCKED_TPT)
329 		wiphy_delayed_work_queue(mld_vif->mld->wiphy,
330 					 &mld_vif->emlsr.check_tpt_wk,
331 					 round_jiffies_relative(IWL_MLD_TPT_COUNT_WINDOW));
332 
333 	if (mld_vif->emlsr.blocked_reasons)
334 		return;
335 
336 	IWL_DEBUG_INFO(mld, "EMLSR is unblocked\n");
337 	iwl_mld_trigger_link_selection(mld, vif);
338 }
339 
340 static void
341 iwl_mld_vif_iter_emlsr_mode_notif(void *data, u8 *mac,
342 				  struct ieee80211_vif *vif)
343 {
344 	struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);
345 	struct iwl_esr_mode_notif *notif = (void *)data;
346 
347 	if (!iwl_mld_vif_has_emlsr_cap(vif))
348 		return;
349 
350 	switch (le32_to_cpu(notif->action)) {
351 	case ESR_RECOMMEND_ENTER:
352 		iwl_mld_unblock_emlsr(mld_vif->mld, vif,
353 				      IWL_MLD_EMLSR_BLOCKED_FW);
354 		break;
355 	case ESR_RECOMMEND_LEAVE:
356 		iwl_mld_block_emlsr(mld_vif->mld, vif,
357 				    IWL_MLD_EMLSR_BLOCKED_FW,
358 				    iwl_mld_get_primary_link(vif));
359 		break;
360 	case ESR_FORCE_LEAVE:
361 	default:
362 		/* ESR_FORCE_LEAVE should not happen at this point */
363 		IWL_WARN(mld_vif->mld, "Unexpected EMLSR notification: %d\n",
364 			 le32_to_cpu(notif->action));
365 	}
366 }
367 
368 void iwl_mld_handle_emlsr_mode_notif(struct iwl_mld *mld,
369 				     struct iwl_rx_packet *pkt)
370 {
371 	ieee80211_iterate_active_interfaces_mtx(mld->hw,
372 						IEEE80211_IFACE_ITER_NORMAL,
373 						iwl_mld_vif_iter_emlsr_mode_notif,
374 						pkt->data);
375 }
376 
377 static void
378 iwl_mld_vif_iter_disconnect_emlsr(void *data, u8 *mac,
379 				  struct ieee80211_vif *vif)
380 {
381 	if (!iwl_mld_vif_has_emlsr_cap(vif))
382 		return;
383 
384 	ieee80211_connection_loss(vif);
385 }
386 
387 void iwl_mld_handle_emlsr_trans_fail_notif(struct iwl_mld *mld,
388 					   struct iwl_rx_packet *pkt)
389 {
390 	const struct iwl_esr_trans_fail_notif *notif = (const void *)pkt->data;
391 	u32 fw_link_id = le32_to_cpu(notif->link_id);
392 	struct ieee80211_bss_conf *bss_conf =
393 		iwl_mld_fw_id_to_link_conf(mld, fw_link_id);
394 
395 	IWL_DEBUG_INFO(mld, "Failed to %s EMLSR on link %d (FW: %d), reason %d\n",
396 		       le32_to_cpu(notif->activation) ? "enter" : "exit",
397 		       bss_conf ? bss_conf->link_id : -1,
398 		       le32_to_cpu(notif->link_id),
399 		       le32_to_cpu(notif->err_code));
400 
401 	if (IWL_FW_CHECK(mld, !bss_conf,
402 			 "FW reported failure to %sactivate EMLSR on a non-existing link: %d\n",
403 			 le32_to_cpu(notif->activation) ? "" : "de",
404 			 fw_link_id)) {
405 		ieee80211_iterate_active_interfaces_mtx(
406 			mld->hw, IEEE80211_IFACE_ITER_NORMAL,
407 			iwl_mld_vif_iter_disconnect_emlsr, NULL);
408 		return;
409 	}
410 
411 	/* Disconnect if we failed to deactivate a link */
412 	if (!le32_to_cpu(notif->activation)) {
413 		ieee80211_connection_loss(bss_conf->vif);
414 		return;
415 	}
416 
417 	/*
418 	 * We failed to activate the second link, go back to the link specified
419 	 * by the firmware as that is the one that is still valid now.
420 	 */
421 	iwl_mld_exit_emlsr(mld, bss_conf->vif, IWL_MLD_EMLSR_EXIT_FAIL_ENTRY,
422 			   bss_conf->link_id);
423 }
424 
425 /* Active non-station link tracking */
426 static void iwl_mld_count_non_bss_links(void *_data, u8 *mac,
427 					struct ieee80211_vif *vif)
428 {
429 	struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);
430 	int *count = _data;
431 
432 	if (ieee80211_vif_type_p2p(vif) == NL80211_IFTYPE_STATION)
433 		return;
434 
435 	*count += iwl_mld_count_active_links(mld_vif->mld, vif);
436 }
437 
438 struct iwl_mld_update_emlsr_block_data {
439 	bool block;
440 	int result;
441 };
442 
443 static void
444 iwl_mld_vif_iter_update_emlsr_non_bss_block(void *_data, u8 *mac,
445 					    struct ieee80211_vif *vif)
446 {
447 	struct iwl_mld_update_emlsr_block_data *data = _data;
448 	struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);
449 	int ret;
450 
451 	if (data->block) {
452 		ret = iwl_mld_block_emlsr_sync(mld_vif->mld, vif,
453 					       IWL_MLD_EMLSR_BLOCKED_NON_BSS,
454 					       iwl_mld_get_primary_link(vif));
455 		if (ret)
456 			data->result = ret;
457 	} else {
458 		iwl_mld_unblock_emlsr(mld_vif->mld, vif,
459 				      IWL_MLD_EMLSR_BLOCKED_NON_BSS);
460 	}
461 }
462 
463 int iwl_mld_emlsr_check_non_bss_block(struct iwl_mld *mld,
464 				      int pending_link_changes)
465 {
466 	/* An active link of a non-station vif blocks EMLSR. Upon activation
467 	 * block EMLSR on the bss vif. Upon deactivation, check if this link
468 	 * was the last non-station link active, and if so unblock the bss vif
469 	 */
470 	struct iwl_mld_update_emlsr_block_data block_data = {};
471 	int count = pending_link_changes;
472 
473 	/* No need to count if we are activating a non-BSS link */
474 	if (count <= 0)
475 		ieee80211_iterate_active_interfaces_mtx(mld->hw,
476 							IEEE80211_IFACE_ITER_NORMAL,
477 							iwl_mld_count_non_bss_links,
478 							&count);
479 
480 	/*
481 	 * We could skip updating it if the block change did not change (and
482 	 * pending_link_changes is non-zero).
483 	 */
484 	block_data.block = !!count;
485 
486 	ieee80211_iterate_active_interfaces_mtx(mld->hw,
487 						IEEE80211_IFACE_ITER_NORMAL,
488 						iwl_mld_vif_iter_update_emlsr_non_bss_block,
489 						&block_data);
490 
491 	return block_data.result;
492 }
493 
494 #define EMLSR_SEC_LINK_MIN_PERC 10
495 #define EMLSR_MIN_TX 3000
496 #define EMLSR_MIN_RX 400
497 
498 void iwl_mld_emlsr_check_tpt(struct wiphy *wiphy, struct wiphy_work *wk)
499 {
500 	struct iwl_mld_vif *mld_vif = container_of(wk, struct iwl_mld_vif,
501 						   emlsr.check_tpt_wk.work);
502 	struct ieee80211_vif *vif =
503 		container_of((void *)mld_vif, struct ieee80211_vif, drv_priv);
504 	struct iwl_mld *mld = mld_vif->mld;
505 	struct iwl_mld_sta *mld_sta;
506 	struct iwl_mld_link *sec_link;
507 	unsigned long total_tx = 0, total_rx = 0;
508 	unsigned long sec_link_tx = 0, sec_link_rx = 0;
509 	u8 sec_link_tx_perc, sec_link_rx_perc;
510 	s8 sec_link_id;
511 
512 	if (!iwl_mld_vif_has_emlsr_cap(vif) || !mld_vif->ap_sta)
513 		return;
514 
515 	mld_sta = iwl_mld_sta_from_mac80211(mld_vif->ap_sta);
516 
517 	/* We only count for the AP sta in a MLO connection */
518 	if (!mld_sta->mpdu_counters)
519 		return;
520 
521 	/* This wk should only run when the TPT blocker isn't set.
522 	 * When the blocker is set, the decision to remove it, as well as
523 	 * clearing the counters is done in DP (to avoid having a wk every
524 	 * 5 seconds when idle. When the blocker is unset, we are not idle anyway)
525 	 */
526 	if (WARN_ON(mld_vif->emlsr.blocked_reasons & IWL_MLD_EMLSR_BLOCKED_TPT))
527 		return;
528 	/*
529 	 * TPT is unblocked, need to check if the TPT criteria is still met.
530 	 *
531 	 * If EMLSR is active, then we also need to check the secondar link
532 	 * requirements.
533 	 */
534 	if (iwl_mld_emlsr_active(vif)) {
535 		sec_link_id = iwl_mld_get_other_link(vif, iwl_mld_get_primary_link(vif));
536 		sec_link = iwl_mld_link_dereference_check(mld_vif, sec_link_id);
537 		if (WARN_ON_ONCE(!sec_link))
538 			return;
539 		/* We need the FW ID here */
540 		sec_link_id = sec_link->fw_id;
541 	} else {
542 		sec_link_id = -1;
543 	}
544 
545 	/* Sum up RX and TX MPDUs from the different queues/links */
546 	for (int q = 0; q < mld->trans->num_rx_queues; q++) {
547 		struct iwl_mld_per_q_mpdu_counter *queue_counter =
548 			&mld_sta->mpdu_counters[q];
549 
550 		spin_lock_bh(&queue_counter->lock);
551 
552 		/* The link IDs that doesn't exist will contain 0 */
553 		for (int link = 0;
554 		     link < ARRAY_SIZE(queue_counter->per_link);
555 		     link++) {
556 			total_tx += queue_counter->per_link[link].tx;
557 			total_rx += queue_counter->per_link[link].rx;
558 		}
559 
560 		if (sec_link_id != -1) {
561 			sec_link_tx += queue_counter->per_link[sec_link_id].tx;
562 			sec_link_rx += queue_counter->per_link[sec_link_id].rx;
563 		}
564 
565 		memset(queue_counter->per_link, 0,
566 		       sizeof(queue_counter->per_link));
567 
568 		spin_unlock_bh(&queue_counter->lock);
569 	}
570 
571 	IWL_DEBUG_INFO(mld, "total Tx MPDUs: %ld. total Rx MPDUs: %ld\n",
572 		       total_tx, total_rx);
573 
574 	/* If we don't have enough MPDUs - exit EMLSR */
575 	if (total_tx < IWL_MLD_ENTER_EMLSR_TPT_THRESH &&
576 	    total_rx < IWL_MLD_ENTER_EMLSR_TPT_THRESH) {
577 		iwl_mld_block_emlsr(mld, vif, IWL_MLD_EMLSR_BLOCKED_TPT,
578 				    iwl_mld_get_primary_link(vif));
579 		return;
580 	}
581 
582 	/* EMLSR is not active */
583 	if (sec_link_id == -1)
584 		return;
585 
586 	IWL_DEBUG_INFO(mld, "Secondary Link %d: Tx MPDUs: %ld. Rx MPDUs: %ld\n",
587 		       sec_link_id, sec_link_tx, sec_link_rx);
588 
589 	/* Calculate the percentage of the secondary link TX/RX */
590 	sec_link_tx_perc = total_tx ? sec_link_tx * 100 / total_tx : 0;
591 	sec_link_rx_perc = total_rx ? sec_link_rx * 100 / total_rx : 0;
592 
593 	/*
594 	 * The TX/RX percentage is checked only if it exceeds the required
595 	 * minimum. In addition, RX is checked only if the TX check failed.
596 	 */
597 	if ((total_tx > EMLSR_MIN_TX &&
598 	     sec_link_tx_perc < EMLSR_SEC_LINK_MIN_PERC) ||
599 	    (total_rx > EMLSR_MIN_RX &&
600 	     sec_link_rx_perc < EMLSR_SEC_LINK_MIN_PERC)) {
601 		iwl_mld_exit_emlsr(mld, vif, IWL_MLD_EMLSR_EXIT_LINK_USAGE,
602 				   iwl_mld_get_primary_link(vif));
603 		return;
604 	}
605 
606 	/* Check again when the next window ends  */
607 	wiphy_delayed_work_queue(mld_vif->mld->wiphy,
608 				 &mld_vif->emlsr.check_tpt_wk,
609 				 round_jiffies_relative(IWL_MLD_TPT_COUNT_WINDOW));
610 }
611 
612 void iwl_mld_emlsr_unblock_tpt_wk(struct wiphy *wiphy, struct wiphy_work *wk)
613 {
614 	struct iwl_mld_vif *mld_vif = container_of(wk, struct iwl_mld_vif,
615 						   emlsr.unblock_tpt_wk);
616 	struct ieee80211_vif *vif =
617 		container_of((void *)mld_vif, struct ieee80211_vif, drv_priv);
618 
619 	iwl_mld_unblock_emlsr(mld_vif->mld, vif, IWL_MLD_EMLSR_BLOCKED_TPT);
620 }
621 
622 /*
623  * Link selection
624  */
625 struct iwl_mld_link_sel_data {
626 	u8 link_id;
627 	const struct cfg80211_chan_def *chandef;
628 	s32 signal;
629 	u16 grade;
630 };
631 
632 s8 iwl_mld_get_emlsr_rssi_thresh(struct iwl_mld *mld,
633 				 const struct cfg80211_chan_def *chandef,
634 				 bool low)
635 {
636 	if (WARN_ON(chandef->chan->band != NL80211_BAND_2GHZ &&
637 		    chandef->chan->band != NL80211_BAND_5GHZ &&
638 		    chandef->chan->band != NL80211_BAND_6GHZ))
639 		return S8_MAX;
640 
641 #define RSSI_THRESHOLD(_low, _bw)			\
642 	(_low) ? IWL_MLD_LOW_RSSI_THRESH_##_bw##MHZ	\
643 	       : IWL_MLD_HIGH_RSSI_THRESH_##_bw##MHZ
644 
645 	switch (chandef->width) {
646 	case NL80211_CHAN_WIDTH_20_NOHT:
647 	case NL80211_CHAN_WIDTH_20:
648 	/* 320 MHz has the same thresholds as 20 MHz */
649 	case NL80211_CHAN_WIDTH_320:
650 		return RSSI_THRESHOLD(low, 20);
651 	case NL80211_CHAN_WIDTH_40:
652 		return RSSI_THRESHOLD(low, 40);
653 	case NL80211_CHAN_WIDTH_80:
654 		return RSSI_THRESHOLD(low, 80);
655 	case NL80211_CHAN_WIDTH_160:
656 		return RSSI_THRESHOLD(low, 160);
657 	default:
658 		WARN_ON(1);
659 		return S8_MAX;
660 	}
661 #undef RSSI_THRESHOLD
662 }
663 
664 static u32
665 iwl_mld_emlsr_disallowed_with_link(struct iwl_mld *mld,
666 				   struct ieee80211_vif *vif,
667 				   struct iwl_mld_link_sel_data *link,
668 				   bool primary)
669 {
670 	struct wiphy *wiphy = mld->wiphy;
671 	struct ieee80211_bss_conf *conf;
672 	enum iwl_mld_emlsr_exit ret = 0;
673 
674 	conf = wiphy_dereference(wiphy, vif->link_conf[link->link_id]);
675 	if (WARN_ON_ONCE(!conf))
676 		return false;
677 
678 	if (link->chandef->chan->band == NL80211_BAND_2GHZ && mld->bt_is_active)
679 		ret |= IWL_MLD_EMLSR_EXIT_BT_COEX;
680 
681 	if (link->signal <
682 	    iwl_mld_get_emlsr_rssi_thresh(mld, link->chandef, false))
683 		ret |= IWL_MLD_EMLSR_EXIT_LOW_RSSI;
684 
685 	if (conf->csa_active)
686 		ret |= IWL_MLD_EMLSR_EXIT_CSA;
687 
688 	if (ret) {
689 		IWL_DEBUG_INFO(mld,
690 			       "Link %d is not allowed for EMLSR as %s\n",
691 			       link->link_id,
692 			       primary ? "primary" : "secondary");
693 		iwl_mld_print_emlsr_exit(mld, ret);
694 	}
695 
696 	return ret;
697 }
698 
699 static u8
700 iwl_mld_set_link_sel_data(struct iwl_mld *mld,
701 			  struct ieee80211_vif *vif,
702 			  struct iwl_mld_link_sel_data *data,
703 			  unsigned long usable_links,
704 			  u8 *best_link_idx)
705 {
706 	u8 n_data = 0;
707 	u16 max_grade = 0;
708 	unsigned long link_id;
709 
710 	/*
711 	 * TODO: don't select links that weren't discovered in the last scan
712 	 * This requires mac80211 (or cfg80211) changes to forward/track when
713 	 * a BSS was last updated. cfg80211 already tracks this information but
714 	 * it is not exposed within the kernel.
715 	 */
716 	for_each_set_bit(link_id, &usable_links, IEEE80211_MLD_MAX_NUM_LINKS) {
717 		struct ieee80211_bss_conf *link_conf =
718 			link_conf_dereference_protected(vif, link_id);
719 
720 		if (WARN_ON_ONCE(!link_conf))
721 			continue;
722 
723 		/* Ignore any BSS that was not seen in the last 5 seconds */
724 		if (ktime_before(link_conf->bss->ts_boottime,
725 				 ktime_sub_ns(ktime_get_boottime_ns(),
726 					      (u64)5 * NSEC_PER_SEC)))
727 			continue;
728 
729 		data[n_data].link_id = link_id;
730 		data[n_data].chandef = &link_conf->chanreq.oper;
731 		data[n_data].signal = MBM_TO_DBM(link_conf->bss->signal);
732 		data[n_data].grade = iwl_mld_get_link_grade(mld, link_conf);
733 
734 		if (n_data == 0 || data[n_data].grade > max_grade) {
735 			max_grade = data[n_data].grade;
736 			*best_link_idx = n_data;
737 		}
738 		n_data++;
739 	}
740 
741 	return n_data;
742 }
743 
744 static bool
745 iwl_mld_valid_emlsr_pair(struct ieee80211_vif *vif,
746 			 struct iwl_mld_link_sel_data *a,
747 			 struct iwl_mld_link_sel_data *b)
748 {
749 	struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);
750 	struct iwl_mld *mld = mld_vif->mld;
751 	enum iwl_mld_emlsr_exit ret = 0;
752 
753 	/* Per-link considerations */
754 	if (iwl_mld_emlsr_disallowed_with_link(mld, vif, a, true) ||
755 	    iwl_mld_emlsr_disallowed_with_link(mld, vif, b, false))
756 		return false;
757 
758 	if (a->chandef->chan->band == b->chandef->chan->band) {
759 		ret |= IWL_MLD_EMLSR_EXIT_EQUAL_BAND;
760 	} else if (a->chandef->width != b->chandef->width) {
761 		/* TODO: task=EMLSR task=statistics
762 		 * replace BANDWIDTH exit reason with channel load criteria
763 		 */
764 		ret |= IWL_MLD_EMLSR_EXIT_BANDWIDTH;
765 	}
766 
767 	if (ret) {
768 		IWL_DEBUG_INFO(mld,
769 			       "Links %d and %d are not a valid pair for EMLSR\n",
770 			       a->link_id, b->link_id);
771 		IWL_DEBUG_INFO(mld,
772 			       "Links bandwidth are: %d and %d\n",
773 			       nl80211_chan_width_to_mhz(a->chandef->width),
774 			       nl80211_chan_width_to_mhz(b->chandef->width));
775 		iwl_mld_print_emlsr_exit(mld, ret);
776 		return false;
777 	}
778 
779 	return true;
780 }
781 
782 /* Calculation is done with fixed-point with a scaling factor of 1/256 */
783 #define SCALE_FACTOR 256
784 
785 /*
786  * Returns the combined grade of two given links.
787  * Returns 0 if EMLSR is not allowed with these 2 links.
788  */
789 static
790 unsigned int iwl_mld_get_emlsr_grade(struct iwl_mld *mld,
791 				     struct ieee80211_vif *vif,
792 				     struct iwl_mld_link_sel_data *a,
793 				     struct iwl_mld_link_sel_data *b,
794 				     u8 *primary_id)
795 {
796 	struct ieee80211_bss_conf *primary_conf;
797 	struct wiphy *wiphy = ieee80211_vif_to_wdev(vif)->wiphy;
798 	unsigned int primary_load;
799 
800 	lockdep_assert_wiphy(wiphy);
801 
802 	/* a is always primary, b is always secondary */
803 	if (b->grade > a->grade)
804 		swap(a, b);
805 
806 	*primary_id = a->link_id;
807 
808 	if (!iwl_mld_valid_emlsr_pair(vif, a, b))
809 		return 0;
810 
811 	primary_conf = wiphy_dereference(wiphy, vif->link_conf[*primary_id]);
812 
813 	if (WARN_ON_ONCE(!primary_conf))
814 		return 0;
815 
816 	primary_load = iwl_mld_get_chan_load(mld, primary_conf);
817 
818 	/* The more the primary link is loaded, the more worthwhile EMLSR becomes */
819 	return a->grade + ((b->grade * primary_load) / SCALE_FACTOR);
820 }
821 
822 static void _iwl_mld_select_links(struct iwl_mld *mld,
823 				  struct ieee80211_vif *vif)
824 {
825 	struct iwl_mld_link_sel_data data[IEEE80211_MLD_MAX_NUM_LINKS];
826 	struct iwl_mld_link_sel_data *best_link;
827 	struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);
828 	int max_active_links = iwl_mld_max_active_links(mld, vif);
829 	u16 new_active, usable_links = ieee80211_vif_usable_links(vif);
830 	u8 best_idx, new_primary, n_data;
831 	u16 max_grade;
832 
833 	lockdep_assert_wiphy(mld->wiphy);
834 
835 	if (!mld_vif->authorized || hweight16(usable_links) <= 1)
836 		return;
837 
838 	if (WARN(time_before(mld->scan.last_mlo_scan_jiffies,
839 			     jiffies - IWL_MLD_SCAN_EXPIRE_TIME),
840 		"Last MLO scan was too long ago, can't select links\n"))
841 		return;
842 
843 	/* The logic below is simple and not suited for more than 2 links */
844 	WARN_ON_ONCE(max_active_links > 2);
845 
846 	n_data = iwl_mld_set_link_sel_data(mld, vif, data, usable_links,
847 					   &best_idx);
848 
849 	if (WARN(!n_data, "Couldn't find a valid grade for any link!\n"))
850 		return;
851 
852 	/* Default to selecting the single best link */
853 	best_link = &data[best_idx];
854 	new_primary = best_link->link_id;
855 	new_active = BIT(best_link->link_id);
856 	max_grade = best_link->grade;
857 
858 	/* If EMLSR is not possible, activate the best link */
859 	if (max_active_links == 1 || n_data == 1 ||
860 	    !iwl_mld_vif_has_emlsr_cap(vif) || !IWL_MLD_AUTO_EML_ENABLE ||
861 	    mld_vif->emlsr.blocked_reasons)
862 		goto set_active;
863 
864 	/* Try to find the best link combination */
865 	for (u8 a = 0; a < n_data; a++) {
866 		for (u8 b = a + 1; b < n_data; b++) {
867 			u8 best_in_pair;
868 			u16 emlsr_grade =
869 				iwl_mld_get_emlsr_grade(mld, vif,
870 							&data[a], &data[b],
871 							&best_in_pair);
872 
873 			/*
874 			 * Prefer (new) EMLSR combination to prefer EMLSR over
875 			 * a single link.
876 			 */
877 			if (emlsr_grade < max_grade)
878 				continue;
879 
880 			max_grade = emlsr_grade;
881 			new_primary = best_in_pair;
882 			new_active = BIT(data[a].link_id) |
883 				     BIT(data[b].link_id);
884 		}
885 	}
886 
887 set_active:
888 	IWL_DEBUG_INFO(mld, "Link selection result: 0x%x. Primary = %d\n",
889 		       new_active, new_primary);
890 
891 	mld_vif->emlsr.selected_primary = new_primary;
892 	mld_vif->emlsr.selected_links = new_active;
893 
894 	ieee80211_set_active_links_async(vif, new_active);
895 }
896 
897 static void iwl_mld_vif_iter_select_links(void *_data, u8 *mac,
898 					  struct ieee80211_vif *vif)
899 {
900 	struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);
901 	struct iwl_mld *mld = mld_vif->mld;
902 
903 	_iwl_mld_select_links(mld, vif);
904 }
905 
906 void iwl_mld_select_links(struct iwl_mld *mld)
907 {
908 	ieee80211_iterate_active_interfaces_mtx(mld->hw,
909 						IEEE80211_IFACE_ITER_NORMAL,
910 						iwl_mld_vif_iter_select_links,
911 						NULL);
912 }
913 
914 void iwl_mld_emlsr_check_equal_bw(struct iwl_mld *mld,
915 				  struct ieee80211_vif *vif,
916 				  struct ieee80211_bss_conf *link)
917 {
918 	u8 other_link_id = iwl_mld_get_other_link(vif, link->link_id);
919 	struct ieee80211_bss_conf *other_link =
920 		link_conf_dereference_check(vif, other_link_id);
921 
922 	if (!ieee80211_vif_link_active(vif, link->link_id) ||
923 	    !iwl_mld_emlsr_active(vif) ||
924 	    WARN_ON(link->link_id == other_link_id || !other_link))
925 		return;
926 
927 	if (link->chanreq.oper.width != other_link->chanreq.oper.width)
928 		iwl_mld_exit_emlsr(mld, vif, IWL_MLD_EMLSR_EXIT_BANDWIDTH,
929 				   iwl_mld_get_primary_link(vif));
930 }
931 
932 static void iwl_mld_emlsr_check_bt_iter(void *_data, u8 *mac,
933 					struct ieee80211_vif *vif)
934 {
935 	struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);
936 	struct iwl_mld *mld = mld_vif->mld;
937 	struct ieee80211_bss_conf *link;
938 	unsigned int link_id;
939 
940 	if (!mld->bt_is_active) {
941 		iwl_mld_retry_emlsr(mld, vif);
942 		return;
943 	}
944 
945 	/* BT is turned ON but we are not in EMLSR, nothing to do */
946 	if (!iwl_mld_emlsr_active(vif))
947 		return;
948 
949 	/* In EMLSR and BT is turned ON */
950 
951 	for_each_vif_active_link(vif, link, link_id) {
952 		if (WARN_ON(!link->chanreq.oper.chan))
953 			continue;
954 
955 		if (link->chanreq.oper.chan->band == NL80211_BAND_2GHZ) {
956 			iwl_mld_exit_emlsr(mld, vif, IWL_MLD_EMLSR_EXIT_BT_COEX,
957 					   iwl_mld_get_primary_link(vif));
958 			return;
959 		}
960 	}
961 }
962 
963 void iwl_mld_emlsr_check_bt(struct iwl_mld *mld)
964 {
965 	ieee80211_iterate_active_interfaces_mtx(mld->hw,
966 						IEEE80211_IFACE_ITER_NORMAL,
967 						iwl_mld_emlsr_check_bt_iter,
968 						NULL);
969 }
970 
971 static void iwl_mld_emlsr_check_chan_load_iter(void *_data, u8 *mac,
972 					       struct ieee80211_vif *vif)
973 {
974 	struct iwl_mld *mld = (struct iwl_mld *)_data;
975 	struct ieee80211_bss_conf *prim_link;
976 	unsigned int prim_link_id;
977 	int chan_load;
978 
979 	if (!iwl_mld_emlsr_active(vif))
980 		return;
981 
982 	prim_link_id = iwl_mld_get_primary_link(vif);
983 	prim_link = link_conf_dereference_protected(vif, prim_link_id);
984 	if (WARN_ON(!prim_link))
985 		return;
986 
987 	chan_load = iwl_mld_get_chan_load_by_others(mld, prim_link, true);
988 
989 	if (chan_load < 0)
990 		return;
991 
992 	/* chan_load is in range [0,255] */
993 	if (chan_load < NORMALIZE_PERCENT_TO_255(IWL_MLD_CHAN_LOAD_THRESH))
994 		iwl_mld_exit_emlsr(mld, vif, IWL_MLD_EMLSR_EXIT_CHAN_LOAD,
995 				   prim_link_id);
996 }
997 
998 void iwl_mld_emlsr_check_chan_load(struct iwl_mld *mld)
999 {
1000 	ieee80211_iterate_active_interfaces_mtx(mld->hw,
1001 						IEEE80211_IFACE_ITER_NORMAL,
1002 						iwl_mld_emlsr_check_chan_load_iter,
1003 						(void *)(uintptr_t)mld);
1004 }
1005 
1006 void iwl_mld_retry_emlsr(struct iwl_mld *mld, struct ieee80211_vif *vif)
1007 {
1008 	struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif);
1009 
1010 	if (!iwl_mld_vif_has_emlsr_cap(vif) || iwl_mld_emlsr_active(vif) ||
1011 	    mld_vif->emlsr.blocked_reasons)
1012 		return;
1013 
1014 	iwl_mld_trigger_link_selection(mld, vif);
1015 }
1016