xref: /linux/drivers/net/wireless/realtek/rtw89/chan.c (revision a34b0e4e21d6be3c3d620aa7f9dfbf0e9550c19e)
1 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
2 /* Copyright(c) 2020-2022  Realtek Corporation
3  */
4 
5 #include "chan.h"
6 #include "coex.h"
7 #include "debug.h"
8 #include "fw.h"
9 #include "mac.h"
10 #include "phy.h"
11 #include "ps.h"
12 #include "sar.h"
13 #include "util.h"
14 
15 static void rtw89_swap_chanctx(struct rtw89_dev *rtwdev,
16 			       enum rtw89_chanctx_idx idx1,
17 			       enum rtw89_chanctx_idx idx2);
18 
19 static enum rtw89_subband rtw89_get_subband_type(enum rtw89_band band,
20 						 u8 center_chan)
21 {
22 	switch (band) {
23 	default:
24 	case RTW89_BAND_2G:
25 		switch (center_chan) {
26 		default:
27 		case 1 ... 14:
28 			return RTW89_CH_2G;
29 		}
30 	case RTW89_BAND_5G:
31 		switch (center_chan) {
32 		default:
33 		case 36 ... 64:
34 			return RTW89_CH_5G_BAND_1;
35 		case 100 ... 144:
36 			return RTW89_CH_5G_BAND_3;
37 		case 149 ... 177:
38 			return RTW89_CH_5G_BAND_4;
39 		}
40 	case RTW89_BAND_6G:
41 		switch (center_chan) {
42 		default:
43 		case 1 ... 29:
44 			return RTW89_CH_6G_BAND_IDX0;
45 		case 33 ... 61:
46 			return RTW89_CH_6G_BAND_IDX1;
47 		case 65 ... 93:
48 			return RTW89_CH_6G_BAND_IDX2;
49 		case 97 ... 125:
50 			return RTW89_CH_6G_BAND_IDX3;
51 		case 129 ... 157:
52 			return RTW89_CH_6G_BAND_IDX4;
53 		case 161 ... 189:
54 			return RTW89_CH_6G_BAND_IDX5;
55 		case 193 ... 221:
56 			return RTW89_CH_6G_BAND_IDX6;
57 		case 225 ... 253:
58 			return RTW89_CH_6G_BAND_IDX7;
59 		}
60 	}
61 }
62 
63 static enum rtw89_tx_comp_band rtw89_get_tx_comp_band(enum rtw89_band band,
64 						      u8 center_chan)
65 {
66 	switch (band) {
67 	default:
68 	case RTW89_BAND_2G:
69 		return RTW89_TX_COMP_BAND_2GHZ;
70 	case RTW89_BAND_5G:
71 		if (center_chan < 149)
72 			return RTW89_TX_COMP_BAND_5GHZ_L;
73 		else
74 			return RTW89_TX_COMP_BAND_5GHZ_H;
75 	case RTW89_BAND_6G:
76 		if (center_chan < 65)
77 			return RTW89_TX_COMP_BAND_5GHZ_H;
78 		else if (center_chan < 193)
79 			return RTW89_TX_COMP_BAND_6GHZ_M;
80 		else
81 			return RTW89_TX_COMP_BAND_6GHZ_UH;
82 	}
83 }
84 
85 static enum rtw89_sc_offset rtw89_get_primary_chan_idx(enum rtw89_bandwidth bw,
86 						       u32 center_freq,
87 						       u32 primary_freq)
88 {
89 	u8 primary_chan_idx;
90 	u32 offset;
91 
92 	switch (bw) {
93 	default:
94 	case RTW89_CHANNEL_WIDTH_20:
95 		primary_chan_idx = RTW89_SC_DONT_CARE;
96 		break;
97 	case RTW89_CHANNEL_WIDTH_40:
98 		if (primary_freq > center_freq)
99 			primary_chan_idx = RTW89_SC_20_UPPER;
100 		else
101 			primary_chan_idx = RTW89_SC_20_LOWER;
102 		break;
103 	case RTW89_CHANNEL_WIDTH_80:
104 	case RTW89_CHANNEL_WIDTH_160:
105 		if (primary_freq > center_freq) {
106 			offset = (primary_freq - center_freq - 10) / 20;
107 			primary_chan_idx = RTW89_SC_20_UPPER + offset * 2;
108 		} else {
109 			offset = (center_freq - primary_freq - 10) / 20;
110 			primary_chan_idx = RTW89_SC_20_LOWER + offset * 2;
111 		}
112 		break;
113 	}
114 
115 	return primary_chan_idx;
116 }
117 
118 static u8 rtw89_get_primary_sb_idx(u8 central_ch, u8 pri_ch,
119 				   enum rtw89_bandwidth bw)
120 {
121 	static const u8 prisb_cal_ofst[RTW89_CHANNEL_WIDTH_ORDINARY_NUM] = {
122 		0, 2, 6, 14, 30
123 	};
124 
125 	if (bw >= RTW89_CHANNEL_WIDTH_ORDINARY_NUM)
126 		return 0;
127 
128 	return (prisb_cal_ofst[bw] + pri_ch - central_ch) / 4;
129 }
130 
131 void rtw89_chan_create(struct rtw89_chan *chan, u8 center_chan, u8 primary_chan,
132 		       enum rtw89_band band, enum rtw89_bandwidth bandwidth)
133 {
134 	enum nl80211_band nl_band = rtw89_hw_to_nl80211_band(band);
135 	u32 center_freq, primary_freq;
136 
137 	memset(chan, 0, sizeof(*chan));
138 	chan->channel = center_chan;
139 	chan->primary_channel = primary_chan;
140 	chan->band_type = band;
141 	chan->band_width = bandwidth;
142 
143 	center_freq = ieee80211_channel_to_frequency(center_chan, nl_band);
144 	primary_freq = ieee80211_channel_to_frequency(primary_chan, nl_band);
145 
146 	chan->freq = center_freq;
147 	chan->subband_type = rtw89_get_subband_type(band, center_chan);
148 	chan->tx_comp_band = rtw89_get_tx_comp_band(band, center_chan);
149 	chan->pri_ch_idx = rtw89_get_primary_chan_idx(bandwidth, center_freq,
150 						      primary_freq);
151 	chan->pri_sb_idx = rtw89_get_primary_sb_idx(center_chan, primary_chan,
152 						    bandwidth);
153 }
154 
155 static void _rtw89_chan_update_punctured(struct rtw89_dev *rtwdev,
156 					 struct rtw89_vif_link *rtwvif_link,
157 					 const struct cfg80211_chan_def *chandef)
158 {
159 	struct ieee80211_bss_conf *bss_conf;
160 
161 	if (rtwvif_link->wifi_role != RTW89_WIFI_ROLE_STATION &&
162 	    rtwvif_link->wifi_role != RTW89_WIFI_ROLE_P2P_CLIENT)
163 		return;
164 
165 	rcu_read_lock();
166 
167 	bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true);
168 	if (!bss_conf->eht_support) {
169 		rcu_read_unlock();
170 		return;
171 	}
172 
173 	rcu_read_unlock();
174 
175 	rtw89_chip_h2c_punctured_cmac_tbl(rtwdev, rtwvif_link, chandef->punctured);
176 }
177 
178 static void rtw89_chan_update_punctured(struct rtw89_dev *rtwdev,
179 					enum rtw89_chanctx_idx idx,
180 					const struct cfg80211_chan_def *chandef)
181 {
182 	struct rtw89_vif_link *rtwvif_link;
183 	struct rtw89_vif *rtwvif;
184 	unsigned int link_id;
185 
186 	rtw89_for_each_rtwvif(rtwdev, rtwvif) {
187 		rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) {
188 			if (!rtwvif_link->chanctx_assigned ||
189 			    rtwvif_link->chanctx_idx != idx)
190 				continue;
191 
192 			_rtw89_chan_update_punctured(rtwdev, rtwvif_link, chandef);
193 		}
194 	}
195 }
196 
197 bool rtw89_assign_entity_chan(struct rtw89_dev *rtwdev,
198 			      enum rtw89_chanctx_idx idx,
199 			      const struct rtw89_chan *new)
200 {
201 	struct rtw89_hal *hal = &rtwdev->hal;
202 	struct rtw89_chan *chan = &hal->chanctx[idx].chan;
203 	struct rtw89_chan_rcd *rcd = &hal->chanctx[idx].rcd;
204 	bool band_changed;
205 
206 	rcd->prev_primary_channel = chan->primary_channel;
207 	rcd->prev_band_type = chan->band_type;
208 	band_changed = new->band_type != chan->band_type;
209 	rcd->band_changed = band_changed;
210 
211 	*chan = *new;
212 	return band_changed;
213 }
214 
215 int rtw89_iterate_entity_chan(struct rtw89_dev *rtwdev,
216 			      int (*iterator)(const struct rtw89_chan *chan,
217 					      void *data),
218 			      void *data)
219 {
220 	struct rtw89_hal *hal = &rtwdev->hal;
221 	const struct rtw89_chan *chan;
222 	int ret;
223 	u8 idx;
224 
225 	lockdep_assert_wiphy(rtwdev->hw->wiphy);
226 
227 	for_each_set_bit(idx,  hal->entity_map, NUM_OF_RTW89_CHANCTX) {
228 		chan = rtw89_chan_get(rtwdev, idx);
229 		ret = iterator(chan, data);
230 		if (ret)
231 			return ret;
232 	}
233 
234 	return 0;
235 }
236 
237 static void __rtw89_config_entity_chandef(struct rtw89_dev *rtwdev,
238 					  enum rtw89_chanctx_idx idx,
239 					  const struct cfg80211_chan_def *chandef)
240 {
241 	struct rtw89_hal *hal = &rtwdev->hal;
242 
243 	hal->chanctx[idx].chandef = *chandef;
244 }
245 
246 void rtw89_config_entity_chandef(struct rtw89_dev *rtwdev,
247 				 enum rtw89_chanctx_idx idx,
248 				 const struct cfg80211_chan_def *chandef)
249 {
250 	struct rtw89_hal *hal = &rtwdev->hal;
251 
252 	if (!chandef) {
253 		clear_bit(idx, hal->entity_map);
254 		return;
255 	}
256 
257 	__rtw89_config_entity_chandef(rtwdev, idx, chandef);
258 	set_bit(idx, hal->entity_map);
259 }
260 
261 void rtw89_config_roc_chandef(struct rtw89_dev *rtwdev,
262 			      struct rtw89_vif_link *rtwvif_link,
263 			      const struct cfg80211_chan_def *chandef)
264 {
265 	enum rtw89_chanctx_idx idx = rtwvif_link->chanctx_idx;
266 	struct rtw89_hal *hal = &rtwdev->hal;
267 	enum rtw89_chanctx_idx cur;
268 
269 	if (chandef) {
270 		cur = atomic_cmpxchg(&hal->roc_chanctx_idx,
271 				     RTW89_CHANCTX_IDLE, idx);
272 		if (cur != RTW89_CHANCTX_IDLE) {
273 			rtw89_debug(rtwdev, RTW89_DBG_TXRX,
274 				    "ROC still processing on entity %d\n", idx);
275 			return;
276 		}
277 
278 		hal->roc_chandef = *chandef;
279 		hal->roc_link_index = rtw89_vif_link_inst_get_index(rtwvif_link);
280 	} else {
281 		cur = atomic_cmpxchg(&hal->roc_chanctx_idx, idx,
282 				     RTW89_CHANCTX_IDLE);
283 		if (cur == idx)
284 			return;
285 
286 		if (cur == RTW89_CHANCTX_IDLE)
287 			rtw89_debug(rtwdev, RTW89_DBG_TXRX,
288 				    "ROC already finished on entity %d\n", idx);
289 		else
290 			rtw89_debug(rtwdev, RTW89_DBG_TXRX,
291 				    "ROC is processing on entity %d\n", cur);
292 	}
293 }
294 
295 static void rtw89_config_default_chandef(struct rtw89_dev *rtwdev)
296 {
297 	struct cfg80211_chan_def chandef = {0};
298 
299 	rtw89_get_default_chandef(&chandef);
300 	__rtw89_config_entity_chandef(rtwdev, RTW89_CHANCTX_0, &chandef);
301 }
302 
303 void rtw89_entity_init(struct rtw89_dev *rtwdev)
304 {
305 	struct rtw89_hal *hal = &rtwdev->hal;
306 	struct rtw89_entity_mgnt *mgnt = &hal->entity_mgnt;
307 	int i, j;
308 
309 	hal->entity_pause = false;
310 	bitmap_zero(hal->entity_map, NUM_OF_RTW89_CHANCTX);
311 	bitmap_zero(hal->changes, NUM_OF_RTW89_CHANCTX_CHANGES);
312 	atomic_set(&hal->roc_chanctx_idx, RTW89_CHANCTX_IDLE);
313 
314 	INIT_LIST_HEAD(&mgnt->active_list);
315 
316 	for (i = 0; i < RTW89_MAX_INTERFACE_NUM; i++) {
317 		for (j = 0; j < __RTW89_MLD_MAX_LINK_NUM; j++)
318 			mgnt->chanctx_tbl[i][j] = RTW89_CHANCTX_IDLE;
319 	}
320 
321 	hal->entity_force_hw = RTW89_PHY_NUM;
322 
323 	rtw89_config_default_chandef(rtwdev);
324 }
325 
326 static bool rtw89_vif_is_active_role(struct rtw89_vif *rtwvif)
327 {
328 	struct rtw89_vif_link *rtwvif_link;
329 	unsigned int link_id;
330 
331 	rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id)
332 		if (rtwvif_link->chanctx_assigned)
333 			return true;
334 
335 	return false;
336 }
337 
338 static void rtw89_entity_calculate_weight(struct rtw89_dev *rtwdev,
339 					  struct rtw89_entity_weight *w)
340 {
341 	struct rtw89_hal *hal = &rtwdev->hal;
342 	const struct rtw89_chanctx_cfg *cfg;
343 	struct rtw89_vif *rtwvif;
344 	int idx;
345 
346 	w->registered_chanctxs = bitmap_weight(hal->entity_map, NUM_OF_RTW89_CHANCTX);
347 
348 	for_each_set_bit(idx, hal->entity_map, NUM_OF_RTW89_CHANCTX) {
349 		cfg = hal->chanctx[idx].cfg;
350 		if (!cfg) {
351 			/* doesn't run with chanctx ops; one channel at most */
352 			w->active_chanctxs = 1;
353 			break;
354 		}
355 
356 		if (cfg->ref_count > 0)
357 			w->active_chanctxs++;
358 	}
359 
360 	rtw89_for_each_rtwvif(rtwdev, rtwvif) {
361 		if (rtw89_vif_is_active_role(rtwvif))
362 			w->active_roles++;
363 	}
364 }
365 
366 static void rtw89_normalize_link_chanctx(struct rtw89_dev *rtwdev,
367 					 struct rtw89_vif_link *rtwvif_link)
368 {
369 	struct rtw89_vif *rtwvif = rtwvif_link->rtwvif;
370 	struct rtw89_vif_link *cur;
371 
372 	if (unlikely(!rtwvif_link->chanctx_assigned))
373 		return;
374 
375 	cur = rtw89_get_designated_link(rtwvif);
376 	if (unlikely(!cur) || !cur->chanctx_assigned)
377 		return;
378 
379 	if (cur == rtwvif_link)
380 		return;
381 
382 	rtw89_swap_chanctx(rtwdev, rtwvif_link->chanctx_idx, cur->chanctx_idx);
383 }
384 
385 const struct rtw89_chan *__rtw89_mgnt_chan_get(struct rtw89_dev *rtwdev,
386 					       const char *caller_message,
387 					       u8 link_index, bool nullchk)
388 {
389 	struct rtw89_hal *hal = &rtwdev->hal;
390 	struct rtw89_entity_mgnt *mgnt = &hal->entity_mgnt;
391 	enum rtw89_chanctx_idx chanctx_idx;
392 	enum rtw89_chanctx_idx roc_idx;
393 	enum rtw89_entity_mode mode;
394 	u8 role_index;
395 
396 	lockdep_assert_wiphy(rtwdev->hw->wiphy);
397 
398 	if (unlikely(link_index >= __RTW89_MLD_MAX_LINK_NUM)) {
399 		WARN(1, "link index %u is invalid (max link inst num: %d)\n",
400 		     link_index, __RTW89_MLD_MAX_LINK_NUM);
401 		goto dflt;
402 	}
403 
404 	mode = rtw89_get_entity_mode(rtwdev);
405 	switch (mode) {
406 	case RTW89_ENTITY_MODE_SCC_OR_SMLD:
407 	case RTW89_ENTITY_MODE_MCC:
408 		role_index = 0;
409 		break;
410 	case RTW89_ENTITY_MODE_MCC_PREPARE:
411 		role_index = 1;
412 		break;
413 	default:
414 		WARN(1, "Invalid ent mode: %d\n", mode);
415 		goto dflt;
416 	}
417 
418 	chanctx_idx = mgnt->chanctx_tbl[role_index][link_index];
419 	if (chanctx_idx == RTW89_CHANCTX_IDLE)
420 		goto dflt;
421 
422 	roc_idx = atomic_read(&hal->roc_chanctx_idx);
423 	if (roc_idx != RTW89_CHANCTX_IDLE) {
424 		/* ROC is ongoing (given ROC runs on @hal->roc_link_index).
425 		 * If @link_index is the same, get the ongoing ROC chanctx.
426 		 */
427 		if (link_index == hal->roc_link_index)
428 			chanctx_idx = roc_idx;
429 	}
430 
431 	return rtw89_chan_get(rtwdev, chanctx_idx);
432 
433 dflt:
434 	if (unlikely(nullchk))
435 		return NULL;
436 
437 	rtw89_debug(rtwdev, RTW89_DBG_CHAN,
438 		    "%s (%s): prefetch NULL on link index %u\n",
439 		    __func__, caller_message ?: "", link_index);
440 
441 	return rtw89_chan_get(rtwdev, RTW89_CHANCTX_0);
442 }
443 EXPORT_SYMBOL(__rtw89_mgnt_chan_get);
444 
445 bool rtw89_entity_check_hw(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx)
446 {
447 	switch (rtwdev->mlo_dbcc_mode) {
448 	case MLO_2_PLUS_0_1RF:
449 		return phy_idx == RTW89_PHY_0;
450 	case MLO_0_PLUS_2_1RF:
451 		return phy_idx == RTW89_PHY_1;
452 	default:
453 		return false;
454 	}
455 }
456 
457 void rtw89_entity_force_hw(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy_idx)
458 {
459 	rtwdev->hal.entity_force_hw = phy_idx;
460 
461 	if (phy_idx != RTW89_PHY_NUM)
462 		rtw89_debug(rtwdev, RTW89_DBG_CHAN, "%s: %d\n", __func__, phy_idx);
463 	else
464 		rtw89_debug(rtwdev, RTW89_DBG_CHAN, "%s: (none)\n", __func__);
465 }
466 
467 static enum rtw89_mlo_dbcc_mode
468 rtw89_entity_sel_mlo_dbcc_mode(struct rtw89_dev *rtwdev, u8 active_hws)
469 {
470 	if (rtwdev->chip->chip_gen != RTW89_CHIP_BE)
471 		return MLO_DBCC_NOT_SUPPORT;
472 
473 	switch (rtwdev->hal.entity_force_hw) {
474 	case RTW89_PHY_0:
475 		return MLO_2_PLUS_0_1RF;
476 	case RTW89_PHY_1:
477 		return MLO_0_PLUS_2_1RF;
478 	default:
479 		break;
480 	}
481 
482 	switch (active_hws) {
483 	case BIT(0):
484 		return MLO_2_PLUS_0_1RF;
485 	case BIT(1):
486 		return MLO_0_PLUS_2_1RF;
487 	case BIT(0) | BIT(1):
488 	default:
489 		return MLO_1_PLUS_1_1RF;
490 	}
491 }
492 
493 static
494 void rtw89_entity_recalc_mlo_dbcc_mode(struct rtw89_dev *rtwdev, u8 active_hws)
495 {
496 	enum rtw89_mlo_dbcc_mode mode;
497 
498 	mode = rtw89_entity_sel_mlo_dbcc_mode(rtwdev, active_hws);
499 	rtwdev->mlo_dbcc_mode = mode;
500 
501 	rtw89_debug(rtwdev, RTW89_DBG_STATE, "recalc mlo dbcc mode to %d\n", mode);
502 }
503 
504 static void rtw89_entity_recalc_mgnt_roles(struct rtw89_dev *rtwdev)
505 {
506 	struct rtw89_hal *hal = &rtwdev->hal;
507 	struct rtw89_entity_mgnt *mgnt = &hal->entity_mgnt;
508 	struct rtw89_vif_link *link;
509 	struct rtw89_vif *role;
510 	u8 active_hws = 0;
511 	u8 pos = 0;
512 	int i, j;
513 
514 	lockdep_assert_wiphy(rtwdev->hw->wiphy);
515 
516 	for (i = 0; i < RTW89_MAX_INTERFACE_NUM; i++)
517 		mgnt->active_roles[i] = NULL;
518 
519 	for (i = 0; i < RTW89_MAX_INTERFACE_NUM; i++) {
520 		for (j = 0; j < __RTW89_MLD_MAX_LINK_NUM; j++)
521 			mgnt->chanctx_tbl[i][j] = RTW89_CHANCTX_IDLE;
522 	}
523 
524 	/* To be consistent with legacy behavior, expect the first active role
525 	 * which uses RTW89_CHANCTX_0 to put at position 0 and its designated
526 	 * link take RTW89_CHANCTX_0. (normalizing)
527 	 */
528 	list_for_each_entry(role, &mgnt->active_list, mgnt_entry) {
529 		for (i = 0; i < role->links_inst_valid_num; i++) {
530 			link = rtw89_vif_get_link_inst(role, i);
531 			if (!link || !link->chanctx_assigned)
532 				continue;
533 
534 			if (link->chanctx_idx == RTW89_CHANCTX_0) {
535 				rtw89_normalize_link_chanctx(rtwdev, link);
536 
537 				list_del(&role->mgnt_entry);
538 				list_add(&role->mgnt_entry, &mgnt->active_list);
539 				goto fill;
540 			}
541 		}
542 	}
543 
544 fill:
545 	list_for_each_entry(role, &mgnt->active_list, mgnt_entry) {
546 		if (unlikely(pos >= RTW89_MAX_INTERFACE_NUM)) {
547 			rtw89_warn(rtwdev,
548 				   "%s: active roles are over max iface num\n",
549 				   __func__);
550 			break;
551 		}
552 
553 		for (i = 0; i < role->links_inst_valid_num; i++) {
554 			link = rtw89_vif_get_link_inst(role, i);
555 			if (!link || !link->chanctx_assigned)
556 				continue;
557 
558 			mgnt->chanctx_tbl[pos][i] = link->chanctx_idx;
559 			active_hws |= BIT(i);
560 		}
561 
562 		mgnt->active_roles[pos++] = role;
563 	}
564 
565 	rtw89_entity_recalc_mlo_dbcc_mode(rtwdev, active_hws);
566 }
567 
568 enum rtw89_entity_mode rtw89_entity_recalc(struct rtw89_dev *rtwdev)
569 {
570 	DECLARE_BITMAP(recalc_map, NUM_OF_RTW89_CHANCTX) = {};
571 	struct rtw89_hal *hal = &rtwdev->hal;
572 	const struct cfg80211_chan_def *chandef;
573 	struct rtw89_entity_weight w = {};
574 	enum rtw89_entity_mode mode;
575 	struct rtw89_chan chan;
576 	u8 idx;
577 
578 	lockdep_assert_wiphy(rtwdev->hw->wiphy);
579 
580 	bitmap_copy(recalc_map, hal->entity_map, NUM_OF_RTW89_CHANCTX);
581 
582 	rtw89_entity_calculate_weight(rtwdev, &w);
583 	switch (w.active_chanctxs) {
584 	default:
585 		rtw89_warn(rtwdev, "unknown ent chanctxs weight: %d\n",
586 			   w.active_chanctxs);
587 		bitmap_zero(recalc_map, NUM_OF_RTW89_CHANCTX);
588 		fallthrough;
589 	case 0:
590 		if (!w.registered_chanctxs)
591 			rtw89_config_default_chandef(rtwdev);
592 		set_bit(RTW89_CHANCTX_0, recalc_map);
593 		fallthrough;
594 	case 1:
595 		mode = RTW89_ENTITY_MODE_SCC_OR_SMLD;
596 		break;
597 	case 2 ... NUM_OF_RTW89_CHANCTX:
598 		if (w.active_roles == 1) {
599 			mode = RTW89_ENTITY_MODE_SCC_OR_SMLD;
600 			break;
601 		}
602 
603 		if (w.active_roles != NUM_OF_RTW89_MCC_ROLES) {
604 			rtw89_debug(rtwdev, RTW89_DBG_CHAN,
605 				    "unhandled ent: %d chanctxs %d roles\n",
606 				    w.active_chanctxs, w.active_roles);
607 			return RTW89_ENTITY_MODE_UNHANDLED;
608 		}
609 
610 		mode = rtw89_get_entity_mode(rtwdev);
611 		if (mode == RTW89_ENTITY_MODE_MCC)
612 			break;
613 
614 		mode = RTW89_ENTITY_MODE_MCC_PREPARE;
615 		break;
616 	}
617 
618 	for_each_set_bit(idx, recalc_map, NUM_OF_RTW89_CHANCTX) {
619 		chandef = rtw89_chandef_get(rtwdev, idx);
620 		rtw89_get_channel_params(chandef, &chan);
621 		if (chan.channel == 0) {
622 			WARN(1, "Invalid channel on chanctx %d\n", idx);
623 			return RTW89_ENTITY_MODE_INVALID;
624 		}
625 
626 		rtw89_assign_entity_chan(rtwdev, idx, &chan);
627 	}
628 
629 	rtw89_entity_recalc_mgnt_roles(rtwdev);
630 
631 	if (hal->entity_pause)
632 		return rtw89_get_entity_mode(rtwdev);
633 
634 	rtw89_set_entity_mode(rtwdev, mode);
635 	return mode;
636 }
637 
638 static void rtw89_chanctx_notify(struct rtw89_dev *rtwdev,
639 				 enum rtw89_chanctx_state state)
640 {
641 	const struct rtw89_chip_info *chip = rtwdev->chip;
642 	const struct rtw89_chanctx_listener *listener = chip->chanctx_listener;
643 	int i;
644 
645 	if (!listener)
646 		return;
647 
648 	for (i = 0; i < NUM_OF_RTW89_CHANCTX_CALLBACKS; i++) {
649 		if (!listener->callbacks[i])
650 			continue;
651 
652 		rtw89_debug(rtwdev, RTW89_DBG_CHAN,
653 			    "chanctx notify listener: cb %d, state %d\n",
654 			    i, state);
655 
656 		listener->callbacks[i](rtwdev, state);
657 	}
658 }
659 
660 static bool rtw89_concurrent_via_mrc(struct rtw89_dev *rtwdev)
661 {
662 	enum rtw89_chip_gen chip_gen = rtwdev->chip->chip_gen;
663 
664 	return chip_gen == RTW89_CHIP_BE;
665 }
666 
667 /* This function centrally manages how MCC roles are sorted and iterated.
668  * And, it guarantees that ordered_idx is less than NUM_OF_RTW89_MCC_ROLES.
669  * So, if data needs to pass an array for ordered_idx, the array can declare
670  * with NUM_OF_RTW89_MCC_ROLES. Besides, the entire iteration will stop
671  * immediately as long as iterator returns a non-zero value.
672  */
673 static
674 int rtw89_iterate_mcc_roles(struct rtw89_dev *rtwdev,
675 			    int (*iterator)(struct rtw89_dev *rtwdev,
676 					    struct rtw89_mcc_role *mcc_role,
677 					    unsigned int ordered_idx,
678 					    void *data),
679 			    void *data)
680 {
681 	struct rtw89_mcc_info *mcc = &rtwdev->mcc;
682 	struct rtw89_mcc_role * const roles[] = {
683 		&mcc->role_ref,
684 		&mcc->role_aux,
685 	};
686 	unsigned int idx;
687 	int ret;
688 
689 	BUILD_BUG_ON(ARRAY_SIZE(roles) != NUM_OF_RTW89_MCC_ROLES);
690 
691 	for (idx = 0; idx < NUM_OF_RTW89_MCC_ROLES; idx++) {
692 		ret = iterator(rtwdev, roles[idx], idx, data);
693 		if (ret)
694 			return ret;
695 	}
696 
697 	return 0;
698 }
699 
700 static u32 rtw89_mcc_get_tbtt_ofst(struct rtw89_dev *rtwdev,
701 				   struct rtw89_mcc_role *role, u64 tsf)
702 {
703 	struct rtw89_vif_link *rtwvif_link = role->rtwvif_link;
704 	u32 bcn_intvl_us = ieee80211_tu_to_usec(role->beacon_interval);
705 	u64 sync_tsf = READ_ONCE(rtwvif_link->sync_bcn_tsf);
706 	u32 remainder;
707 
708 	if (role->is_go) {
709 		sync_tsf = 0;
710 	} else if (tsf < sync_tsf) {
711 		rtw89_debug(rtwdev, RTW89_DBG_CHAN,
712 			    "MCC get tbtt ofst: tsf might not update yet\n");
713 		sync_tsf = 0;
714 	}
715 
716 	div_u64_rem(tsf - sync_tsf, bcn_intvl_us, &remainder);
717 
718 	return remainder;
719 }
720 
721 static int __mcc_fw_req_tsf(struct rtw89_dev *rtwdev, u64 *tsf_ref, u64 *tsf_aux)
722 {
723 	struct rtw89_mcc_info *mcc = &rtwdev->mcc;
724 	struct rtw89_mcc_role *ref = &mcc->role_ref;
725 	struct rtw89_mcc_role *aux = &mcc->role_aux;
726 	struct rtw89_mac_mcc_tsf_rpt rpt = {};
727 	struct rtw89_fw_mcc_tsf_req req = {};
728 	int ret;
729 
730 	req.group = mcc->group;
731 	req.macid_x = ref->rtwvif_link->mac_id;
732 	req.macid_y = aux->rtwvif_link->mac_id;
733 	ret = rtw89_fw_h2c_mcc_req_tsf(rtwdev, &req, &rpt);
734 	if (ret) {
735 		rtw89_debug(rtwdev, RTW89_DBG_CHAN,
736 			    "MCC h2c failed to request tsf: %d\n", ret);
737 		return ret;
738 	}
739 
740 	*tsf_ref = (u64)rpt.tsf_x_high << 32 | rpt.tsf_x_low;
741 	*tsf_aux = (u64)rpt.tsf_y_high << 32 | rpt.tsf_y_low;
742 
743 	return 0;
744 }
745 
746 static int __mrc_fw_req_tsf(struct rtw89_dev *rtwdev, u64 *tsf_ref, u64 *tsf_aux)
747 {
748 	struct rtw89_mcc_info *mcc = &rtwdev->mcc;
749 	struct rtw89_mcc_role *ref = &mcc->role_ref;
750 	struct rtw89_mcc_role *aux = &mcc->role_aux;
751 	struct rtw89_fw_mrc_req_tsf_arg arg = {};
752 	struct rtw89_mac_mrc_tsf_rpt rpt = {};
753 	int ret;
754 
755 	BUILD_BUG_ON(RTW89_MAC_MRC_MAX_REQ_TSF_NUM < NUM_OF_RTW89_MCC_ROLES);
756 
757 	arg.num = 2;
758 	arg.infos[0].band = ref->rtwvif_link->mac_idx;
759 	arg.infos[0].port = ref->rtwvif_link->port;
760 	arg.infos[1].band = aux->rtwvif_link->mac_idx;
761 	arg.infos[1].port = aux->rtwvif_link->port;
762 
763 	ret = rtw89_fw_h2c_mrc_req_tsf(rtwdev, &arg, &rpt);
764 	if (ret) {
765 		rtw89_debug(rtwdev, RTW89_DBG_CHAN,
766 			    "MRC h2c failed to request tsf: %d\n", ret);
767 		return ret;
768 	}
769 
770 	*tsf_ref = rpt.tsfs[0];
771 	*tsf_aux = rpt.tsfs[1];
772 
773 	return 0;
774 }
775 
776 static u16 rtw89_mcc_get_bcn_ofst(struct rtw89_dev *rtwdev)
777 {
778 	struct rtw89_mcc_info *mcc = &rtwdev->mcc;
779 	struct rtw89_mcc_role *ref = &mcc->role_ref;
780 	struct rtw89_mcc_role *aux = &mcc->role_aux;
781 	u32 bcn_intvl_ref_us = ieee80211_tu_to_usec(ref->beacon_interval);
782 	u32 tbtt_ofst_ref, tbtt_ofst_aux;
783 	u64 tsf_ref, tsf_aux;
784 	int ret;
785 
786 	if (rtw89_concurrent_via_mrc(rtwdev))
787 		ret = __mrc_fw_req_tsf(rtwdev, &tsf_ref, &tsf_aux);
788 	else
789 		ret = __mcc_fw_req_tsf(rtwdev, &tsf_ref, &tsf_aux);
790 
791 	if (ret)
792 		return RTW89_MCC_DFLT_BCN_OFST_TIME;
793 
794 	tbtt_ofst_ref = rtw89_mcc_get_tbtt_ofst(rtwdev, ref, tsf_ref);
795 	tbtt_ofst_aux = rtw89_mcc_get_tbtt_ofst(rtwdev, aux, tsf_aux);
796 
797 	while (tbtt_ofst_ref < tbtt_ofst_aux)
798 		tbtt_ofst_ref += bcn_intvl_ref_us;
799 
800 	return (tbtt_ofst_ref - tbtt_ofst_aux) / 1024;
801 }
802 
803 static
804 void rtw89_mcc_role_fw_macid_bitmap_set_bit(struct rtw89_mcc_role *mcc_role,
805 					    unsigned int bit)
806 {
807 	unsigned int idx = bit / 8;
808 	unsigned int pos = bit % 8;
809 
810 	if (idx >= ARRAY_SIZE(mcc_role->macid_bitmap))
811 		return;
812 
813 	mcc_role->macid_bitmap[idx] |= BIT(pos);
814 }
815 
816 static
817 u32 rtw89_mcc_role_fw_macid_bitmap_to_u32(struct rtw89_mcc_role *mcc_role)
818 {
819 	unsigned int macid;
820 	unsigned int i, j;
821 	u32 bitmap = 0;
822 
823 	for (i = 0; i < ARRAY_SIZE(mcc_role->macid_bitmap); i++) {
824 		for (j = 0; j < 8; j++) {
825 			macid = i * 8 + j;
826 			if (macid >= 32)
827 				goto out;
828 
829 			if (mcc_role->macid_bitmap[i] & BIT(j))
830 				bitmap |= BIT(macid);
831 		}
832 	}
833 
834 out:
835 	return bitmap;
836 }
837 
838 static void rtw89_mcc_role_macid_sta_iter(void *data, struct ieee80211_sta *sta)
839 {
840 	struct rtw89_mcc_role *mcc_role = data;
841 	struct rtw89_vif *target = mcc_role->rtwvif_link->rtwvif;
842 	struct rtw89_sta *rtwsta = sta_to_rtwsta(sta);
843 	struct rtw89_vif *rtwvif = rtwsta->rtwvif;
844 	u8 macid;
845 
846 	if (rtwvif != target)
847 		return;
848 
849 	macid = rtw89_sta_get_main_macid(rtwsta);
850 	rtw89_mcc_role_fw_macid_bitmap_set_bit(mcc_role, macid);
851 }
852 
853 static void rtw89_mcc_fill_role_macid_bitmap(struct rtw89_dev *rtwdev,
854 					     struct rtw89_mcc_role *mcc_role)
855 {
856 	struct rtw89_vif_link *rtwvif_link = mcc_role->rtwvif_link;
857 
858 	rtw89_mcc_role_fw_macid_bitmap_set_bit(mcc_role, rtwvif_link->mac_id);
859 	ieee80211_iterate_stations_atomic(rtwdev->hw,
860 					  rtw89_mcc_role_macid_sta_iter,
861 					  mcc_role);
862 }
863 
864 static void rtw89_mcc_fill_role_policy(struct rtw89_dev *rtwdev,
865 				       struct rtw89_mcc_role *mcc_role)
866 {
867 	struct rtw89_mcc_policy *policy = &mcc_role->policy;
868 
869 	policy->c2h_rpt = RTW89_FW_MCC_C2H_RPT_ALL;
870 	policy->tx_null_early = RTW89_MCC_DFLT_TX_NULL_EARLY;
871 	policy->in_curr_ch = false;
872 	policy->dis_sw_retry = true;
873 	policy->sw_retry_count = false;
874 
875 	if (mcc_role->is_go)
876 		policy->dis_tx_null = true;
877 	else
878 		policy->dis_tx_null = false;
879 }
880 
881 static void rtw89_mcc_fill_role_limit(struct rtw89_dev *rtwdev,
882 				      struct rtw89_mcc_role *mcc_role)
883 {
884 	struct rtw89_vif_link *rtwvif_link = mcc_role->rtwvif_link;
885 	struct ieee80211_p2p_noa_desc *noa_desc;
886 	struct ieee80211_bss_conf *bss_conf;
887 	u32 bcn_intvl_us = ieee80211_tu_to_usec(mcc_role->beacon_interval);
888 	u32 max_toa_us, max_tob_us, max_dur_us;
889 	u32 start_time, interval, duration;
890 	u64 tsf, tsf_lmt;
891 	int ret;
892 	int i;
893 
894 	if (!mcc_role->is_gc)
895 		return;
896 
897 	rtw89_p2p_noa_once_recalc(rtwvif_link);
898 
899 	rcu_read_lock();
900 
901 	bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true);
902 
903 	/* find the first periodic NoA */
904 	for (i = 0; i < RTW89_P2P_MAX_NOA_NUM; i++) {
905 		noa_desc = &bss_conf->p2p_noa_attr.desc[i];
906 		if (noa_desc->count == 255)
907 			goto fill;
908 	}
909 
910 	rcu_read_unlock();
911 	return;
912 
913 fill:
914 	start_time = le32_to_cpu(noa_desc->start_time);
915 	interval = le32_to_cpu(noa_desc->interval);
916 	duration = le32_to_cpu(noa_desc->duration);
917 
918 	rcu_read_unlock();
919 
920 	if (interval != bcn_intvl_us) {
921 		rtw89_debug(rtwdev, RTW89_DBG_CHAN,
922 			    "MCC role limit: mismatch interval: %d vs. %d\n",
923 			    interval, bcn_intvl_us);
924 		return;
925 	}
926 
927 	ret = rtw89_mac_port_get_tsf(rtwdev, rtwvif_link, &tsf);
928 	if (ret) {
929 		rtw89_warn(rtwdev, "MCC failed to get port tsf: %d\n", ret);
930 		return;
931 	}
932 
933 	tsf_lmt = (tsf & GENMASK_ULL(63, 32)) | start_time;
934 	if (tsf_lmt < tsf)
935 		tsf_lmt += roundup_u64(tsf - tsf_lmt, interval);
936 
937 	max_toa_us = rtw89_mcc_get_tbtt_ofst(rtwdev, mcc_role, tsf_lmt);
938 	max_dur_us = interval - duration;
939 	max_tob_us = max_dur_us - max_toa_us;
940 
941 	if (!max_toa_us || !max_tob_us) {
942 		rtw89_debug(rtwdev, RTW89_DBG_CHAN,
943 			    "MCC role limit: hit boundary\n");
944 		return;
945 	}
946 
947 	if (max_dur_us < max_toa_us) {
948 		rtw89_debug(rtwdev, RTW89_DBG_CHAN,
949 			    "MCC role limit: insufficient duration\n");
950 		return;
951 	}
952 
953 	mcc_role->limit.max_toa = max_toa_us / 1024;
954 	mcc_role->limit.max_tob = max_tob_us / 1024;
955 	mcc_role->limit.max_dur = mcc_role->limit.max_toa + mcc_role->limit.max_tob;
956 	mcc_role->limit.enable = true;
957 
958 	rtw89_debug(rtwdev, RTW89_DBG_CHAN,
959 		    "MCC role limit: max_toa %d, max_tob %d, max_dur %d\n",
960 		    mcc_role->limit.max_toa, mcc_role->limit.max_tob,
961 		    mcc_role->limit.max_dur);
962 }
963 
964 static int rtw89_mcc_fill_role(struct rtw89_dev *rtwdev,
965 			       struct rtw89_vif_link *rtwvif_link,
966 			       struct rtw89_mcc_role *role)
967 {
968 	struct ieee80211_bss_conf *bss_conf;
969 	const struct rtw89_chan *chan;
970 
971 	memset(role, 0, sizeof(*role));
972 	role->rtwvif_link = rtwvif_link;
973 
974 	rcu_read_lock();
975 
976 	bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true);
977 	role->beacon_interval = bss_conf->beacon_int;
978 
979 	rcu_read_unlock();
980 
981 	if (!role->beacon_interval) {
982 		rtw89_warn(rtwdev,
983 			   "cannot handle MCC role without beacon interval\n");
984 		return -EINVAL;
985 	}
986 
987 	role->duration = role->beacon_interval / 2;
988 
989 	chan = rtw89_chan_get(rtwdev, rtwvif_link->chanctx_idx);
990 	role->is_2ghz = chan->band_type == RTW89_BAND_2G;
991 	role->is_go = rtwvif_link->wifi_role == RTW89_WIFI_ROLE_P2P_GO;
992 	role->is_gc = rtwvif_link->wifi_role == RTW89_WIFI_ROLE_P2P_CLIENT;
993 
994 	rtw89_mcc_fill_role_macid_bitmap(rtwdev, role);
995 	rtw89_mcc_fill_role_policy(rtwdev, role);
996 	rtw89_mcc_fill_role_limit(rtwdev, role);
997 
998 	rtw89_debug(rtwdev, RTW89_DBG_CHAN,
999 		    "MCC role: bcn_intvl %d, is_2ghz %d, is_go %d, is_gc %d\n",
1000 		    role->beacon_interval, role->is_2ghz, role->is_go, role->is_gc);
1001 	return 0;
1002 }
1003 
1004 static void rtw89_mcc_fill_bt_role(struct rtw89_dev *rtwdev)
1005 {
1006 	struct rtw89_mcc_info *mcc = &rtwdev->mcc;
1007 	struct rtw89_mcc_bt_role *bt_role = &mcc->bt_role;
1008 
1009 	memset(bt_role, 0, sizeof(*bt_role));
1010 	bt_role->duration = rtw89_coex_query_bt_req_len(rtwdev, RTW89_PHY_0);
1011 
1012 	rtw89_debug(rtwdev, RTW89_DBG_CHAN, "MCC bt role: dur %d\n",
1013 		    bt_role->duration);
1014 }
1015 
1016 struct rtw89_mcc_fill_role_selector {
1017 	struct rtw89_vif_link *bind_vif[NUM_OF_RTW89_CHANCTX];
1018 };
1019 
1020 static_assert((u8)NUM_OF_RTW89_CHANCTX >= NUM_OF_RTW89_MCC_ROLES);
1021 static_assert(RTW89_MAX_INTERFACE_NUM >= NUM_OF_RTW89_MCC_ROLES);
1022 
1023 static int rtw89_mcc_fill_role_iterator(struct rtw89_dev *rtwdev,
1024 					struct rtw89_mcc_role *mcc_role,
1025 					unsigned int ordered_idx,
1026 					void *data)
1027 {
1028 	struct rtw89_mcc_fill_role_selector *sel = data;
1029 	struct rtw89_vif_link *role_vif = sel->bind_vif[ordered_idx];
1030 	int ret;
1031 
1032 	if (!role_vif) {
1033 		rtw89_warn(rtwdev, "cannot handle MCC without role[%d]\n",
1034 			   ordered_idx);
1035 		return -EINVAL;
1036 	}
1037 
1038 	rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1039 		    "MCC fill role[%d] with vif <macid %d>\n",
1040 		    ordered_idx, role_vif->mac_id);
1041 
1042 	ret = rtw89_mcc_fill_role(rtwdev, role_vif, mcc_role);
1043 	if (ret)
1044 		return ret;
1045 
1046 	return 0;
1047 }
1048 
1049 static int rtw89_mcc_fill_all_roles(struct rtw89_dev *rtwdev)
1050 {
1051 	struct rtw89_hal *hal = &rtwdev->hal;
1052 	struct rtw89_entity_mgnt *mgnt = &hal->entity_mgnt;
1053 	struct rtw89_mcc_fill_role_selector sel = {};
1054 	struct rtw89_vif_link *rtwvif_link;
1055 	struct rtw89_vif *rtwvif;
1056 	int ret;
1057 	int i;
1058 
1059 	for (i = 0; i < NUM_OF_RTW89_MCC_ROLES; i++) {
1060 		rtwvif = mgnt->active_roles[i];
1061 		if (!rtwvif)
1062 			break;
1063 
1064 		rtwvif_link = rtw89_vif_get_link_inst(rtwvif, 0);
1065 		if (unlikely(!rtwvif_link)) {
1066 			rtw89_err(rtwdev, "mcc fill roles: find no link on HW-0\n");
1067 			continue;
1068 		}
1069 
1070 		sel.bind_vif[i] = rtwvif_link;
1071 		rtw89_p2p_disable_all_noa(rtwdev, rtwvif_link, NULL);
1072 	}
1073 
1074 	ret = rtw89_iterate_mcc_roles(rtwdev, rtw89_mcc_fill_role_iterator, &sel);
1075 	if (ret)
1076 		return ret;
1077 
1078 	rtw89_mcc_fill_bt_role(rtwdev);
1079 	return 0;
1080 }
1081 
1082 static bool rtw89_mcc_can_courtesy(const struct rtw89_mcc_role *provider,
1083 				   const struct rtw89_mcc_role *receiver)
1084 {
1085 	if (provider->is_go || receiver->is_gc)
1086 		return false;
1087 
1088 	return true;
1089 }
1090 
1091 static void rtw89_mcc_assign_pattern(struct rtw89_dev *rtwdev,
1092 				     const struct rtw89_mcc_pattern *new)
1093 {
1094 	struct rtw89_mcc_info *mcc = &rtwdev->mcc;
1095 	struct rtw89_mcc_role *ref = &mcc->role_ref;
1096 	struct rtw89_mcc_role *aux = &mcc->role_aux;
1097 	struct rtw89_mcc_config *config = &mcc->config;
1098 	struct rtw89_mcc_pattern *pattern = &config->pattern;
1099 	struct rtw89_mcc_courtesy_cfg *crtz;
1100 
1101 	rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1102 		    "MCC assign pattern: ref {%d | %d}, aux {%d | %d}\n",
1103 		    new->tob_ref, new->toa_ref, new->tob_aux, new->toa_aux);
1104 
1105 	rtw89_debug(rtwdev, RTW89_DBG_CHAN, "MCC pattern plan: %d\n", new->plan);
1106 
1107 	*pattern = *new;
1108 	memset(&pattern->courtesy, 0, sizeof(pattern->courtesy));
1109 
1110 	if (RTW89_MCC_REQ_COURTESY(pattern, aux) && aux->is_gc)
1111 		aux->ignore_bcn = true;
1112 	else
1113 		aux->ignore_bcn = false;
1114 
1115 	if (RTW89_MCC_REQ_COURTESY(pattern, aux) && rtw89_mcc_can_courtesy(ref, aux)) {
1116 		crtz = &pattern->courtesy.ref;
1117 		ref->crtz = crtz;
1118 
1119 		crtz->macid_tgt = aux->rtwvif_link->mac_id;
1120 		crtz->slot_num = RTW89_MCC_DFLT_COURTESY_SLOT;
1121 
1122 		rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1123 			    "MCC courtesy ref: tgt %d, slot %d\n",
1124 			    crtz->macid_tgt, crtz->slot_num);
1125 	} else {
1126 		ref->crtz = NULL;
1127 	}
1128 
1129 	if (RTW89_MCC_REQ_COURTESY(pattern, ref) && ref->is_gc)
1130 		ref->ignore_bcn = true;
1131 	else
1132 		ref->ignore_bcn = false;
1133 
1134 	if (RTW89_MCC_REQ_COURTESY(pattern, ref) && rtw89_mcc_can_courtesy(aux, ref)) {
1135 		crtz = &pattern->courtesy.aux;
1136 		aux->crtz = crtz;
1137 
1138 		crtz->macid_tgt = ref->rtwvif_link->mac_id;
1139 		crtz->slot_num = RTW89_MCC_DFLT_COURTESY_SLOT;
1140 
1141 		rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1142 			    "MCC courtesy aux: tgt %d, slot %d\n",
1143 			    crtz->macid_tgt, crtz->slot_num);
1144 	} else {
1145 		aux->crtz = NULL;
1146 	}
1147 }
1148 
1149 /* The follow-up roughly shows the relationship between the parameters
1150  * for pattern calculation.
1151  *
1152  * |<    duration ref     >| (if mid bt) |<    duration aux     >|
1153  * |< tob ref >|< toa ref >|     ...     |< tob aux >|< toa aux >|
1154  *             V                                     V
1155  *         tbtt ref                              tbtt aux
1156  *             |<           beacon offset           >|
1157  *
1158  * In loose pattern calculation, we only ensure at least tob_ref and
1159  * toa_ref have positive results. If tob_aux or toa_aux is negative
1160  * unfortunately, FW will be notified to handle it with courtesy
1161  * mechanism.
1162  */
1163 static void __rtw89_mcc_calc_pattern_loose(struct rtw89_dev *rtwdev,
1164 					   struct rtw89_mcc_pattern *ptrn,
1165 					   bool hdl_bt)
1166 {
1167 	struct rtw89_mcc_info *mcc = &rtwdev->mcc;
1168 	struct rtw89_mcc_role *ref = &mcc->role_ref;
1169 	struct rtw89_mcc_role *aux = &mcc->role_aux;
1170 	struct rtw89_mcc_config *config = &mcc->config;
1171 	u16 mcc_intvl = config->mcc_interval;
1172 	u16 bcn_ofst = config->beacon_offset;
1173 	u16 bt_dur_in_mid = 0;
1174 	u16 max_bcn_ofst;
1175 	s16 upper, lower;
1176 	u16 res;
1177 
1178 	*ptrn = (typeof(*ptrn)){
1179 		.plan = hdl_bt ? RTW89_MCC_PLAN_TAIL_BT : RTW89_MCC_PLAN_NO_BT,
1180 	};
1181 
1182 	if (!hdl_bt)
1183 		goto calc;
1184 
1185 	max_bcn_ofst = ref->duration + aux->duration;
1186 	if (ref->limit.enable)
1187 		max_bcn_ofst = min_t(u16, max_bcn_ofst,
1188 				     ref->limit.max_toa + aux->duration);
1189 	else if (aux->limit.enable)
1190 		max_bcn_ofst = min_t(u16, max_bcn_ofst,
1191 				     ref->duration + aux->limit.max_tob);
1192 
1193 	if (bcn_ofst > max_bcn_ofst && bcn_ofst >= mcc->bt_role.duration) {
1194 		bt_dur_in_mid = mcc->bt_role.duration;
1195 		ptrn->plan = RTW89_MCC_PLAN_MID_BT;
1196 	}
1197 
1198 calc:
1199 	rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1200 		    "MCC calc ptrn_ls: plan %d, bcn_ofst %d\n",
1201 		    ptrn->plan, bcn_ofst);
1202 
1203 	res = bcn_ofst - bt_dur_in_mid;
1204 	upper = min_t(s16, ref->duration, res);
1205 	lower = max_t(s16, 0, ref->duration - (mcc_intvl - bcn_ofst));
1206 
1207 	if (ref->limit.enable) {
1208 		upper = min_t(s16, upper, ref->limit.max_toa);
1209 		lower = max_t(s16, lower, ref->duration - ref->limit.max_tob);
1210 	} else if (aux->limit.enable) {
1211 		upper = min_t(s16, upper,
1212 			      res - (aux->duration - aux->limit.max_toa));
1213 		lower = max_t(s16, lower, res - aux->limit.max_tob);
1214 	}
1215 
1216 	if (lower < upper)
1217 		ptrn->toa_ref = (upper + lower) / 2;
1218 	else
1219 		ptrn->toa_ref = lower;
1220 
1221 	ptrn->tob_ref = ref->duration - ptrn->toa_ref;
1222 	ptrn->tob_aux = res - ptrn->toa_ref;
1223 	ptrn->toa_aux = aux->duration - ptrn->tob_aux;
1224 }
1225 
1226 /* In strict pattern calculation, we consider timing that might need
1227  * for HW stuffs, i.e. min_tob and min_toa.
1228  */
1229 static int __rtw89_mcc_calc_pattern_strict(struct rtw89_dev *rtwdev,
1230 					   struct rtw89_mcc_pattern *ptrn)
1231 {
1232 	struct rtw89_mcc_info *mcc = &rtwdev->mcc;
1233 	struct rtw89_mcc_role *ref = &mcc->role_ref;
1234 	struct rtw89_mcc_role *aux = &mcc->role_aux;
1235 	struct rtw89_mcc_config *config = &mcc->config;
1236 	u16 min_tob = RTW89_MCC_EARLY_RX_BCN_TIME + RTW89_MCC_SWITCH_CH_TIME;
1237 	u16 min_toa = RTW89_MCC_MIN_RX_BCN_TIME;
1238 	u16 bcn_ofst = config->beacon_offset;
1239 	s16 upper_toa_ref, lower_toa_ref;
1240 	s16 upper_tob_aux, lower_tob_aux;
1241 	u16 bt_dur_in_mid;
1242 	s16 res;
1243 
1244 	rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1245 		    "MCC calc ptrn_st: plan %d, bcn_ofst %d\n",
1246 		    ptrn->plan, bcn_ofst);
1247 
1248 	if (ptrn->plan == RTW89_MCC_PLAN_MID_BT)
1249 		bt_dur_in_mid = mcc->bt_role.duration;
1250 	else
1251 		bt_dur_in_mid = 0;
1252 
1253 	if (ref->duration < min_tob + min_toa) {
1254 		rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1255 			    "MCC calc ptrn_st: not meet ref dur cond\n");
1256 		return -EINVAL;
1257 	}
1258 
1259 	if (aux->duration < min_tob + min_toa) {
1260 		rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1261 			    "MCC calc ptrn_st: not meet aux dur cond\n");
1262 		return -EINVAL;
1263 	}
1264 
1265 	res = bcn_ofst - min_toa - min_tob - bt_dur_in_mid;
1266 	if (res < 0) {
1267 		rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1268 			    "MCC calc ptrn_st: not meet bcn_ofst cond\n");
1269 		return -EINVAL;
1270 	}
1271 
1272 	upper_toa_ref = min_t(s16, min_toa + res, ref->duration - min_tob);
1273 	lower_toa_ref = min_toa;
1274 	upper_tob_aux = min_t(s16, min_tob + res, aux->duration - min_toa);
1275 	lower_tob_aux = min_tob;
1276 
1277 	if (ref->limit.enable) {
1278 		if (min_tob > ref->limit.max_tob || min_toa > ref->limit.max_toa) {
1279 			rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1280 				    "MCC calc ptrn_st: conflict ref limit\n");
1281 			return -EINVAL;
1282 		}
1283 
1284 		upper_toa_ref = min_t(s16, upper_toa_ref, ref->limit.max_toa);
1285 		lower_toa_ref = max_t(s16, lower_toa_ref,
1286 				      ref->duration - ref->limit.max_tob);
1287 	} else if (aux->limit.enable) {
1288 		if (min_tob > aux->limit.max_tob || min_toa > aux->limit.max_toa) {
1289 			rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1290 				    "MCC calc ptrn_st: conflict aux limit\n");
1291 			return -EINVAL;
1292 		}
1293 
1294 		upper_tob_aux = min_t(s16, upper_tob_aux, aux->limit.max_tob);
1295 		lower_tob_aux = max_t(s16, lower_tob_aux,
1296 				      aux->duration - aux->limit.max_toa);
1297 	}
1298 
1299 	upper_toa_ref = min_t(s16, upper_toa_ref,
1300 			      bcn_ofst - bt_dur_in_mid - lower_tob_aux);
1301 	lower_toa_ref = max_t(s16, lower_toa_ref,
1302 			      bcn_ofst - bt_dur_in_mid - upper_tob_aux);
1303 	if (lower_toa_ref > upper_toa_ref) {
1304 		rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1305 			    "MCC calc ptrn_st: conflict boundary\n");
1306 		return -EINVAL;
1307 	}
1308 
1309 	ptrn->toa_ref = (upper_toa_ref + lower_toa_ref) / 2;
1310 	ptrn->tob_ref = ref->duration - ptrn->toa_ref;
1311 	ptrn->tob_aux = bcn_ofst - ptrn->toa_ref - bt_dur_in_mid;
1312 	ptrn->toa_aux = aux->duration - ptrn->tob_aux;
1313 	return 0;
1314 }
1315 
1316 static void __rtw89_mcc_fill_ptrn_anchor_ref(struct rtw89_dev *rtwdev,
1317 					     struct rtw89_mcc_pattern *ptrn,
1318 					     bool small_bcn_ofst)
1319 {
1320 	struct rtw89_mcc_info *mcc = &rtwdev->mcc;
1321 	struct rtw89_mcc_role *ref = &mcc->role_ref;
1322 	struct rtw89_mcc_role *aux = &mcc->role_aux;
1323 	struct rtw89_mcc_config *config = &mcc->config;
1324 	u16 bcn_ofst = config->beacon_offset;
1325 	u16 ref_tob;
1326 	u16 ref_toa;
1327 
1328 	if (ref->limit.enable) {
1329 		ref_tob = ref->limit.max_tob;
1330 		ref_toa = ref->limit.max_toa;
1331 	} else {
1332 		ref_tob = ref->duration / 2;
1333 		ref_toa = ref->duration / 2;
1334 	}
1335 
1336 	if (small_bcn_ofst) {
1337 		ptrn->toa_ref = ref_toa;
1338 		ptrn->tob_ref = ref->duration - ptrn->toa_ref;
1339 	} else {
1340 		ptrn->tob_ref = ref_tob;
1341 		ptrn->toa_ref = ref->duration - ptrn->tob_ref;
1342 	}
1343 
1344 	ptrn->tob_aux = bcn_ofst - ptrn->toa_ref;
1345 	ptrn->toa_aux = aux->duration - ptrn->tob_aux;
1346 }
1347 
1348 static void __rtw89_mcc_fill_ptrn_anchor_aux(struct rtw89_dev *rtwdev,
1349 					     struct rtw89_mcc_pattern *ptrn,
1350 					     bool small_bcn_ofst)
1351 {
1352 	struct rtw89_mcc_info *mcc = &rtwdev->mcc;
1353 	struct rtw89_mcc_role *ref = &mcc->role_ref;
1354 	struct rtw89_mcc_role *aux = &mcc->role_aux;
1355 	struct rtw89_mcc_config *config = &mcc->config;
1356 	u16 bcn_ofst = config->beacon_offset;
1357 	u16 aux_tob;
1358 	u16 aux_toa;
1359 
1360 	if (aux->limit.enable) {
1361 		aux_tob = aux->limit.max_tob;
1362 		aux_toa = aux->limit.max_toa;
1363 	} else {
1364 		aux_tob = aux->duration / 2;
1365 		aux_toa = aux->duration / 2;
1366 	}
1367 
1368 	if (small_bcn_ofst) {
1369 		ptrn->tob_aux = aux_tob;
1370 		ptrn->toa_aux = aux->duration - ptrn->tob_aux;
1371 	} else {
1372 		ptrn->toa_aux = aux_toa;
1373 		ptrn->tob_aux = aux->duration - ptrn->toa_aux;
1374 	}
1375 
1376 	ptrn->toa_ref = bcn_ofst - ptrn->tob_aux;
1377 	ptrn->tob_ref = ref->duration - ptrn->toa_ref;
1378 }
1379 
1380 static int __rtw89_mcc_calc_pattern_anchor(struct rtw89_dev *rtwdev,
1381 					   struct rtw89_mcc_pattern *ptrn,
1382 					   bool hdl_bt)
1383 {
1384 	struct rtw89_mcc_info *mcc = &rtwdev->mcc;
1385 	struct rtw89_mcc_role *ref = &mcc->role_ref;
1386 	struct rtw89_mcc_role *aux = &mcc->role_aux;
1387 	struct rtw89_mcc_config *config = &mcc->config;
1388 	u16 mcc_intvl = config->mcc_interval;
1389 	u16 bcn_ofst = config->beacon_offset;
1390 	bool small_bcn_ofst;
1391 
1392 	if (bcn_ofst < RTW89_MCC_MIN_RX_BCN_WITH_SWITCH_CH_TIME)
1393 		small_bcn_ofst = true;
1394 	else if (bcn_ofst < aux->duration - aux->limit.max_toa)
1395 		small_bcn_ofst = true;
1396 	else if (mcc_intvl - bcn_ofst < RTW89_MCC_MIN_RX_BCN_WITH_SWITCH_CH_TIME)
1397 		small_bcn_ofst = false;
1398 	else
1399 		return -EPERM;
1400 
1401 	*ptrn = (typeof(*ptrn)){
1402 		.plan = hdl_bt ? RTW89_MCC_PLAN_TAIL_BT : RTW89_MCC_PLAN_NO_BT,
1403 	};
1404 
1405 	rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1406 		    "MCC calc ptrn_ac: plan %d, bcn_ofst %d\n",
1407 		    ptrn->plan, bcn_ofst);
1408 
1409 	if (ref->is_go || ref->is_gc)
1410 		__rtw89_mcc_fill_ptrn_anchor_ref(rtwdev, ptrn, small_bcn_ofst);
1411 	else if (aux->is_go || aux->is_gc)
1412 		__rtw89_mcc_fill_ptrn_anchor_aux(rtwdev, ptrn, small_bcn_ofst);
1413 	else
1414 		__rtw89_mcc_fill_ptrn_anchor_ref(rtwdev, ptrn, small_bcn_ofst);
1415 
1416 	return 0;
1417 }
1418 
1419 static int rtw89_mcc_calc_pattern(struct rtw89_dev *rtwdev, bool hdl_bt)
1420 {
1421 	struct rtw89_mcc_info *mcc = &rtwdev->mcc;
1422 	struct rtw89_mcc_role *ref = &mcc->role_ref;
1423 	struct rtw89_mcc_role *aux = &mcc->role_aux;
1424 	bool sel_plan[NUM_OF_RTW89_MCC_PLAN] = {};
1425 	struct rtw89_mcc_pattern ptrn;
1426 	int ret;
1427 	int i;
1428 
1429 	if (ref->limit.enable && aux->limit.enable) {
1430 		rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1431 			    "MCC calc ptrn: not support dual limited roles\n");
1432 		return -EINVAL;
1433 	}
1434 
1435 	if (ref->limit.enable &&
1436 	    ref->duration > ref->limit.max_tob + ref->limit.max_toa) {
1437 		rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1438 			    "MCC calc ptrn: not fit ref limit\n");
1439 		return -EINVAL;
1440 	}
1441 
1442 	if (aux->limit.enable &&
1443 	    aux->duration > aux->limit.max_tob + aux->limit.max_toa) {
1444 		rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1445 			    "MCC calc ptrn: not fit aux limit\n");
1446 		return -EINVAL;
1447 	}
1448 
1449 	if (hdl_bt) {
1450 		sel_plan[RTW89_MCC_PLAN_TAIL_BT] = true;
1451 		sel_plan[RTW89_MCC_PLAN_MID_BT] = true;
1452 	} else {
1453 		sel_plan[RTW89_MCC_PLAN_NO_BT] = true;
1454 	}
1455 
1456 	for (i = 0; i < NUM_OF_RTW89_MCC_PLAN; i++) {
1457 		if (!sel_plan[i])
1458 			continue;
1459 
1460 		ptrn = (typeof(ptrn)){
1461 			.plan = i,
1462 		};
1463 
1464 		ret = __rtw89_mcc_calc_pattern_strict(rtwdev, &ptrn);
1465 		if (ret)
1466 			rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1467 				    "MCC calc ptrn_st with plan %d: fail\n", i);
1468 		else
1469 			goto done;
1470 	}
1471 
1472 	ret = __rtw89_mcc_calc_pattern_anchor(rtwdev, &ptrn, hdl_bt);
1473 	if (!ret)
1474 		goto done;
1475 
1476 	__rtw89_mcc_calc_pattern_loose(rtwdev, &ptrn, hdl_bt);
1477 
1478 done:
1479 	rtw89_mcc_assign_pattern(rtwdev, &ptrn);
1480 	return 0;
1481 }
1482 
1483 static void rtw89_mcc_set_default_pattern(struct rtw89_dev *rtwdev)
1484 {
1485 	struct rtw89_mcc_info *mcc = &rtwdev->mcc;
1486 	struct rtw89_mcc_role *ref = &mcc->role_ref;
1487 	struct rtw89_mcc_role *aux = &mcc->role_aux;
1488 	struct rtw89_mcc_pattern tmp = {};
1489 
1490 	rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1491 		    "MCC use default pattern unexpectedly\n");
1492 
1493 	tmp.plan = RTW89_MCC_PLAN_NO_BT;
1494 	tmp.tob_ref = ref->duration / 2;
1495 	tmp.toa_ref = ref->duration - tmp.tob_ref;
1496 	tmp.tob_aux = aux->duration / 2;
1497 	tmp.toa_aux = aux->duration - tmp.tob_aux;
1498 
1499 	rtw89_mcc_assign_pattern(rtwdev, &tmp);
1500 }
1501 
1502 static void rtw89_mcc_set_duration_go_sta(struct rtw89_dev *rtwdev,
1503 					  struct rtw89_mcc_role *role_go,
1504 					  struct rtw89_mcc_role *role_sta)
1505 {
1506 	struct rtw89_mcc_info *mcc = &rtwdev->mcc;
1507 	struct rtw89_mcc_config *config = &mcc->config;
1508 	u16 mcc_intvl = config->mcc_interval;
1509 	u16 dur_go, dur_sta;
1510 
1511 	dur_go = clamp_t(u16, role_go->duration, RTW89_MCC_MIN_GO_DURATION,
1512 			 mcc_intvl - RTW89_MCC_MIN_STA_DURATION);
1513 	if (role_go->limit.enable)
1514 		dur_go = min(dur_go, role_go->limit.max_dur);
1515 	dur_sta = mcc_intvl - dur_go;
1516 
1517 	rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1518 		    "MCC set dur: (go, sta) {%d, %d} -> {%d, %d}\n",
1519 		    role_go->duration, role_sta->duration, dur_go, dur_sta);
1520 
1521 	role_go->duration = dur_go;
1522 	role_sta->duration = dur_sta;
1523 }
1524 
1525 static void rtw89_mcc_set_duration_gc_sta(struct rtw89_dev *rtwdev)
1526 {
1527 	struct rtw89_mcc_info *mcc = &rtwdev->mcc;
1528 	struct rtw89_mcc_role *ref = &mcc->role_ref;
1529 	struct rtw89_mcc_role *aux = &mcc->role_aux;
1530 	struct rtw89_mcc_config *config = &mcc->config;
1531 	u16 mcc_intvl = config->mcc_interval;
1532 	u16 dur_ref, dur_aux;
1533 
1534 	if (ref->duration < RTW89_MCC_MIN_STA_DURATION) {
1535 		dur_ref = RTW89_MCC_MIN_STA_DURATION;
1536 		dur_aux = mcc_intvl - dur_ref;
1537 	} else if (aux->duration < RTW89_MCC_MIN_STA_DURATION) {
1538 		dur_aux = RTW89_MCC_MIN_STA_DURATION;
1539 		dur_ref = mcc_intvl - dur_aux;
1540 	} else {
1541 		dur_ref = ref->duration;
1542 		dur_aux = mcc_intvl - dur_ref;
1543 	}
1544 
1545 	if (ref->limit.enable) {
1546 		dur_ref = min(dur_ref, ref->limit.max_dur);
1547 		dur_aux = mcc_intvl - dur_ref;
1548 	} else if (aux->limit.enable) {
1549 		dur_aux = min(dur_aux, aux->limit.max_dur);
1550 		dur_ref = mcc_intvl - dur_aux;
1551 	}
1552 
1553 	rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1554 		    "MCC set dur: (ref, aux) {%d ~ %d} -> {%d ~ %d}\n",
1555 		    ref->duration, aux->duration, dur_ref, dur_aux);
1556 
1557 	ref->duration = dur_ref;
1558 	aux->duration = dur_aux;
1559 }
1560 
1561 struct rtw89_mcc_mod_dur_data {
1562 	u16 available;
1563 	struct {
1564 		u16 dur;
1565 		u16 room;
1566 	} parm[NUM_OF_RTW89_MCC_ROLES];
1567 };
1568 
1569 static int rtw89_mcc_mod_dur_get_iterator(struct rtw89_dev *rtwdev,
1570 					  struct rtw89_mcc_role *mcc_role,
1571 					  unsigned int ordered_idx,
1572 					  void *data)
1573 {
1574 	struct rtw89_mcc_mod_dur_data *p = data;
1575 	u16 min;
1576 
1577 	p->parm[ordered_idx].dur = mcc_role->duration;
1578 
1579 	if (mcc_role->is_go)
1580 		min = RTW89_MCC_MIN_GO_DURATION;
1581 	else
1582 		min = RTW89_MCC_MIN_STA_DURATION;
1583 
1584 	p->parm[ordered_idx].room = max_t(s32, p->parm[ordered_idx].dur - min, 0);
1585 
1586 	rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1587 		    "MCC mod dur: chk role[%u]: dur %u, min %u, room %u\n",
1588 		    ordered_idx, p->parm[ordered_idx].dur, min,
1589 		    p->parm[ordered_idx].room);
1590 
1591 	p->available += p->parm[ordered_idx].room;
1592 	return 0;
1593 }
1594 
1595 static int rtw89_mcc_mod_dur_put_iterator(struct rtw89_dev *rtwdev,
1596 					  struct rtw89_mcc_role *mcc_role,
1597 					  unsigned int ordered_idx,
1598 					  void *data)
1599 {
1600 	struct rtw89_mcc_mod_dur_data *p = data;
1601 
1602 	mcc_role->duration = p->parm[ordered_idx].dur;
1603 
1604 	rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1605 		    "MCC mod dur: set role[%u]: dur %u\n",
1606 		    ordered_idx, p->parm[ordered_idx].dur);
1607 	return 0;
1608 }
1609 
1610 static void rtw89_mcc_mod_duration_dual_2ghz_with_bt(struct rtw89_dev *rtwdev)
1611 {
1612 	struct rtw89_mcc_info *mcc = &rtwdev->mcc;
1613 	struct rtw89_mcc_config *config = &mcc->config;
1614 	struct rtw89_mcc_mod_dur_data data = {};
1615 	u16 mcc_intvl = config->mcc_interval;
1616 	u16 bt_dur = mcc->bt_role.duration;
1617 	u16 wifi_dur;
1618 
1619 	rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1620 		    "MCC mod dur (dual 2ghz): mcc_intvl %u, raw bt_dur %u\n",
1621 		    mcc_intvl, bt_dur);
1622 
1623 	rtw89_iterate_mcc_roles(rtwdev, rtw89_mcc_mod_dur_get_iterator, &data);
1624 
1625 	bt_dur = clamp_t(u16, bt_dur, 1, data.available / 3);
1626 	wifi_dur = mcc_intvl - bt_dur;
1627 
1628 	if (data.parm[0].room <= data.parm[1].room) {
1629 		data.parm[0].dur -= min_t(u16, bt_dur / 2, data.parm[0].room);
1630 		data.parm[1].dur = wifi_dur - data.parm[0].dur;
1631 	} else {
1632 		data.parm[1].dur -= min_t(u16, bt_dur / 2, data.parm[1].room);
1633 		data.parm[0].dur = wifi_dur - data.parm[1].dur;
1634 	}
1635 
1636 	rtw89_iterate_mcc_roles(rtwdev, rtw89_mcc_mod_dur_put_iterator, &data);
1637 
1638 	rtw89_debug(rtwdev, RTW89_DBG_CHAN, "MCC mod dur: set bt: dur %u\n", bt_dur);
1639 	mcc->bt_role.duration = bt_dur;
1640 }
1641 
1642 static
1643 void rtw89_mcc_mod_duration_diff_band_with_bt(struct rtw89_dev *rtwdev,
1644 					      struct rtw89_mcc_role *role_2ghz,
1645 					      struct rtw89_mcc_role *role_non_2ghz)
1646 {
1647 	struct rtw89_mcc_info *mcc = &rtwdev->mcc;
1648 	struct rtw89_mcc_config *config = &mcc->config;
1649 	u16 dur_2ghz, dur_non_2ghz;
1650 	u16 bt_dur, mcc_intvl;
1651 
1652 	dur_2ghz = role_2ghz->duration;
1653 	dur_non_2ghz = role_non_2ghz->duration;
1654 	mcc_intvl = config->mcc_interval;
1655 	bt_dur = mcc->bt_role.duration;
1656 
1657 	rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1658 		    "MCC mod dur (diff band): mcc_intvl %u, bt_dur %u\n",
1659 		    mcc_intvl, bt_dur);
1660 
1661 	rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1662 		    "MCC mod dur: check dur_2ghz %u, dur_non_2ghz %u\n",
1663 		    dur_2ghz, dur_non_2ghz);
1664 
1665 	if (dur_non_2ghz >= bt_dur) {
1666 		rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1667 			    "MCC mod dur: dur_non_2ghz is enough for bt\n");
1668 		return;
1669 	}
1670 
1671 	dur_non_2ghz = bt_dur;
1672 	dur_2ghz = mcc_intvl - dur_non_2ghz;
1673 
1674 	if (role_non_2ghz->limit.enable) {
1675 		rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1676 			    "MCC mod dur: dur_non_2ghz is limited with max %u\n",
1677 			    role_non_2ghz->limit.max_dur);
1678 
1679 		dur_non_2ghz = min(dur_non_2ghz, role_non_2ghz->limit.max_dur);
1680 		dur_2ghz = mcc_intvl - dur_non_2ghz;
1681 	}
1682 
1683 	rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1684 		    "MCC mod dur: set dur_2ghz %u, dur_non_2ghz %u\n",
1685 		    dur_2ghz, dur_non_2ghz);
1686 
1687 	role_2ghz->duration = dur_2ghz;
1688 	role_non_2ghz->duration = dur_non_2ghz;
1689 }
1690 
1691 static bool rtw89_mcc_duration_decision_on_bt(struct rtw89_dev *rtwdev)
1692 {
1693 	struct rtw89_mcc_info *mcc = &rtwdev->mcc;
1694 	struct rtw89_mcc_role *ref = &mcc->role_ref;
1695 	struct rtw89_mcc_role *aux = &mcc->role_aux;
1696 	struct rtw89_mcc_bt_role *bt_role = &mcc->bt_role;
1697 
1698 	if (!bt_role->duration)
1699 		return false;
1700 
1701 	if (ref->is_2ghz && aux->is_2ghz) {
1702 		rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1703 			    "MCC dual roles are on 2GHz; consider BT duration\n");
1704 
1705 		rtw89_mcc_mod_duration_dual_2ghz_with_bt(rtwdev);
1706 		return true;
1707 	}
1708 
1709 	if (!ref->is_2ghz && !aux->is_2ghz) {
1710 		rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1711 			    "MCC dual roles are not on 2GHz; ignore BT duration\n");
1712 		return false;
1713 	}
1714 
1715 	rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1716 		    "MCC one role is on 2GHz; modify another for BT duration\n");
1717 
1718 	if (ref->is_2ghz)
1719 		rtw89_mcc_mod_duration_diff_band_with_bt(rtwdev, ref, aux);
1720 	else
1721 		rtw89_mcc_mod_duration_diff_band_with_bt(rtwdev, aux, ref);
1722 
1723 	return false;
1724 }
1725 
1726 void rtw89_mcc_prepare_done_work(struct wiphy *wiphy, struct wiphy_work *work)
1727 {
1728 	struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
1729 						mcc_prepare_done_work.work);
1730 
1731 	lockdep_assert_wiphy(wiphy);
1732 
1733 	ieee80211_wake_queues(rtwdev->hw);
1734 }
1735 
1736 static void rtw89_mcc_prepare(struct rtw89_dev *rtwdev, bool start)
1737 {
1738 	struct rtw89_mcc_info *mcc = &rtwdev->mcc;
1739 	struct rtw89_mcc_config *config = &mcc->config;
1740 
1741 	if (start) {
1742 		ieee80211_stop_queues(rtwdev->hw);
1743 
1744 		wiphy_delayed_work_queue(rtwdev->hw->wiphy,
1745 					 &rtwdev->mcc_prepare_done_work,
1746 					 usecs_to_jiffies(config->prepare_delay));
1747 	} else {
1748 		wiphy_delayed_work_queue(rtwdev->hw->wiphy,
1749 					 &rtwdev->mcc_prepare_done_work, 0);
1750 		wiphy_delayed_work_flush(rtwdev->hw->wiphy,
1751 					 &rtwdev->mcc_prepare_done_work);
1752 	}
1753 }
1754 
1755 static int rtw89_mcc_fill_start_tsf(struct rtw89_dev *rtwdev)
1756 {
1757 	struct rtw89_mcc_info *mcc = &rtwdev->mcc;
1758 	struct rtw89_mcc_role *ref = &mcc->role_ref;
1759 	struct rtw89_mcc_role *aux = &mcc->role_aux;
1760 	struct rtw89_mcc_config *config = &mcc->config;
1761 	u32 bcn_intvl_ref_us = ieee80211_tu_to_usec(ref->beacon_interval);
1762 	s32 tob_ref_us = ieee80211_tu_to_usec(config->pattern.tob_ref);
1763 	u64 tsf, start_tsf;
1764 	u32 cur_tbtt_ofst;
1765 	u64 min_time;
1766 	u64 tsf_aux;
1767 	int ret;
1768 
1769 	if (rtw89_concurrent_via_mrc(rtwdev))
1770 		ret = __mrc_fw_req_tsf(rtwdev, &tsf, &tsf_aux);
1771 	else
1772 		ret = __mcc_fw_req_tsf(rtwdev, &tsf, &tsf_aux);
1773 
1774 	if (ret)
1775 		return ret;
1776 
1777 	min_time = tsf;
1778 	if (ref->is_go || aux->is_go)
1779 		min_time += ieee80211_tu_to_usec(RTW89_MCC_SHORT_TRIGGER_TIME);
1780 	else
1781 		min_time += ieee80211_tu_to_usec(RTW89_MCC_LONG_TRIGGER_TIME);
1782 
1783 	cur_tbtt_ofst = rtw89_mcc_get_tbtt_ofst(rtwdev, ref, tsf);
1784 	start_tsf = tsf - cur_tbtt_ofst + bcn_intvl_ref_us - tob_ref_us;
1785 	if (start_tsf < min_time)
1786 		start_tsf += roundup_u64(min_time - start_tsf, bcn_intvl_ref_us);
1787 
1788 	config->start_tsf = start_tsf;
1789 	config->start_tsf_in_aux_domain = tsf_aux + start_tsf - tsf;
1790 	config->prepare_delay = start_tsf - tsf;
1791 
1792 	return 0;
1793 }
1794 
1795 static int rtw89_mcc_fill_config(struct rtw89_dev *rtwdev)
1796 {
1797 	struct rtw89_mcc_info *mcc = &rtwdev->mcc;
1798 	struct rtw89_mcc_role *ref = &mcc->role_ref;
1799 	struct rtw89_mcc_role *aux = &mcc->role_aux;
1800 	struct rtw89_mcc_config *config = &mcc->config;
1801 	bool hdl_bt;
1802 	int ret;
1803 
1804 	memset(config, 0, sizeof(*config));
1805 
1806 	switch (mcc->mode) {
1807 	case RTW89_MCC_MODE_GO_STA:
1808 		config->beacon_offset = rtw89_mcc_get_bcn_ofst(rtwdev);
1809 		if (ref->is_go) {
1810 			config->mcc_interval = ref->beacon_interval;
1811 			rtw89_mcc_set_duration_go_sta(rtwdev, ref, aux);
1812 		} else {
1813 			config->mcc_interval = aux->beacon_interval;
1814 			rtw89_mcc_set_duration_go_sta(rtwdev, aux, ref);
1815 		}
1816 		break;
1817 	case RTW89_MCC_MODE_GC_STA:
1818 		config->beacon_offset = rtw89_mcc_get_bcn_ofst(rtwdev);
1819 		config->mcc_interval = ref->beacon_interval;
1820 		rtw89_mcc_set_duration_gc_sta(rtwdev);
1821 		break;
1822 	default:
1823 		rtw89_warn(rtwdev, "MCC unknown mode: %d\n", mcc->mode);
1824 		return -EFAULT;
1825 	}
1826 
1827 	hdl_bt = rtw89_mcc_duration_decision_on_bt(rtwdev);
1828 	rtw89_debug(rtwdev, RTW89_DBG_CHAN, "MCC handle bt: %d\n", hdl_bt);
1829 
1830 	ret = rtw89_mcc_calc_pattern(rtwdev, hdl_bt);
1831 	if (!ret)
1832 		goto bottom;
1833 
1834 	rtw89_mcc_set_default_pattern(rtwdev);
1835 
1836 bottom:
1837 	return rtw89_mcc_fill_start_tsf(rtwdev);
1838 }
1839 
1840 static int __mcc_fw_add_role(struct rtw89_dev *rtwdev, struct rtw89_mcc_role *role)
1841 {
1842 	const struct rtw89_mcc_courtesy_cfg *crtz = role->crtz;
1843 	struct rtw89_mcc_info *mcc = &rtwdev->mcc;
1844 	struct rtw89_mcc_policy *policy = &role->policy;
1845 	struct rtw89_fw_mcc_add_req req = {};
1846 	const struct rtw89_chan *chan;
1847 	int ret;
1848 
1849 	chan = rtw89_chan_get(rtwdev, role->rtwvif_link->chanctx_idx);
1850 	req.central_ch_seg0 = chan->channel;
1851 	req.primary_ch = chan->primary_channel;
1852 	req.bandwidth = chan->band_width;
1853 	req.ch_band_type = chan->band_type;
1854 
1855 	req.macid = role->rtwvif_link->mac_id;
1856 	req.group = mcc->group;
1857 	req.c2h_rpt = policy->c2h_rpt;
1858 	req.tx_null_early = policy->tx_null_early;
1859 	req.dis_tx_null = policy->dis_tx_null;
1860 	req.in_curr_ch = policy->in_curr_ch;
1861 	req.sw_retry_count = policy->sw_retry_count;
1862 	req.dis_sw_retry = policy->dis_sw_retry;
1863 	req.duration = role->duration;
1864 	req.btc_in_2g = false;
1865 
1866 	if (crtz) {
1867 		req.courtesy_target = crtz->macid_tgt;
1868 		req.courtesy_num = crtz->slot_num;
1869 		req.courtesy_en = true;
1870 	}
1871 
1872 	ret = rtw89_fw_h2c_add_mcc(rtwdev, &req);
1873 	if (ret) {
1874 		rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1875 			    "MCC h2c failed to add wifi role: %d\n", ret);
1876 		return ret;
1877 	}
1878 
1879 	ret = rtw89_fw_h2c_mcc_macid_bitmap(rtwdev, mcc->group,
1880 					    role->rtwvif_link->mac_id,
1881 					    role->macid_bitmap);
1882 	if (ret) {
1883 		rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1884 			    "MCC h2c failed to set macid bitmap: %d\n", ret);
1885 		return ret;
1886 	}
1887 
1888 	return 0;
1889 }
1890 
1891 static
1892 void __mrc_fw_add_role(struct rtw89_dev *rtwdev, struct rtw89_mcc_role *role,
1893 		       struct rtw89_fw_mrc_add_arg *arg, u8 slot_idx)
1894 {
1895 	struct rtw89_mcc_info *mcc = &rtwdev->mcc;
1896 	struct rtw89_mcc_role *ref = &mcc->role_ref;
1897 	struct rtw89_mcc_policy *policy = &role->policy;
1898 	struct rtw89_fw_mrc_add_slot_arg *slot_arg;
1899 	const struct rtw89_chan *chan;
1900 
1901 	slot_arg = &arg->slots[slot_idx];
1902 	role->slot_idx = slot_idx;
1903 
1904 	slot_arg->duration = role->duration;
1905 	slot_arg->role_num = 1;
1906 
1907 	chan = rtw89_chan_get(rtwdev, role->rtwvif_link->chanctx_idx);
1908 
1909 	slot_arg->roles[0].role_type = RTW89_H2C_MRC_ROLE_WIFI;
1910 	slot_arg->roles[0].is_master = role == ref;
1911 	slot_arg->roles[0].band = chan->band_type;
1912 	slot_arg->roles[0].bw = chan->band_width;
1913 	slot_arg->roles[0].central_ch = chan->channel;
1914 	slot_arg->roles[0].primary_ch = chan->primary_channel;
1915 	slot_arg->roles[0].en_tx_null = !policy->dis_tx_null;
1916 	slot_arg->roles[0].null_early = policy->tx_null_early;
1917 	slot_arg->roles[0].macid = role->rtwvif_link->mac_id;
1918 	slot_arg->roles[0].macid_main_bitmap =
1919 		rtw89_mcc_role_fw_macid_bitmap_to_u32(role);
1920 }
1921 
1922 static int __mcc_fw_add_bt_role(struct rtw89_dev *rtwdev)
1923 {
1924 	struct rtw89_mcc_info *mcc = &rtwdev->mcc;
1925 	struct rtw89_mcc_bt_role *bt_role = &mcc->bt_role;
1926 	struct rtw89_fw_mcc_add_req req = {};
1927 	int ret;
1928 
1929 	req.group = mcc->group;
1930 	req.duration = bt_role->duration;
1931 	req.btc_in_2g = true;
1932 
1933 	ret = rtw89_fw_h2c_add_mcc(rtwdev, &req);
1934 	if (ret) {
1935 		rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1936 			    "MCC h2c failed to add bt role: %d\n", ret);
1937 		return ret;
1938 	}
1939 
1940 	return 0;
1941 }
1942 
1943 static
1944 void __mrc_fw_add_bt_role(struct rtw89_dev *rtwdev,
1945 			  struct rtw89_fw_mrc_add_arg *arg, u8 slot_idx)
1946 {
1947 	struct rtw89_mcc_info *mcc = &rtwdev->mcc;
1948 	struct rtw89_mcc_bt_role *bt_role = &mcc->bt_role;
1949 	struct rtw89_fw_mrc_add_slot_arg *slot_arg = &arg->slots[slot_idx];
1950 
1951 	slot_arg->duration = bt_role->duration;
1952 	slot_arg->role_num = 1;
1953 
1954 	slot_arg->roles[0].role_type = RTW89_H2C_MRC_ROLE_BT;
1955 }
1956 
1957 static int __mcc_fw_start(struct rtw89_dev *rtwdev, bool replace)
1958 {
1959 	struct rtw89_mcc_info *mcc = &rtwdev->mcc;
1960 	struct rtw89_mcc_role *ref = &mcc->role_ref;
1961 	struct rtw89_mcc_role *aux = &mcc->role_aux;
1962 	struct rtw89_mcc_config *config = &mcc->config;
1963 	struct rtw89_mcc_pattern *pattern = &config->pattern;
1964 	struct rtw89_mcc_sync *sync = &config->sync;
1965 	struct rtw89_fw_mcc_start_req req = {};
1966 	int ret;
1967 
1968 	if (replace) {
1969 		req.old_group = mcc->group;
1970 		req.old_group_action = RTW89_FW_MCC_OLD_GROUP_ACT_REPLACE;
1971 		mcc->group = RTW89_MCC_NEXT_GROUP(mcc->group);
1972 	}
1973 
1974 	req.group = mcc->group;
1975 
1976 	switch (pattern->plan) {
1977 	case RTW89_MCC_PLAN_TAIL_BT:
1978 		ret = __mcc_fw_add_role(rtwdev, ref);
1979 		if (ret)
1980 			return ret;
1981 		ret = __mcc_fw_add_role(rtwdev, aux);
1982 		if (ret)
1983 			return ret;
1984 		ret = __mcc_fw_add_bt_role(rtwdev);
1985 		if (ret)
1986 			return ret;
1987 
1988 		req.btc_in_group = true;
1989 		break;
1990 	case RTW89_MCC_PLAN_MID_BT:
1991 		ret = __mcc_fw_add_role(rtwdev, ref);
1992 		if (ret)
1993 			return ret;
1994 		ret = __mcc_fw_add_bt_role(rtwdev);
1995 		if (ret)
1996 			return ret;
1997 		ret = __mcc_fw_add_role(rtwdev, aux);
1998 		if (ret)
1999 			return ret;
2000 
2001 		req.btc_in_group = true;
2002 		break;
2003 	case RTW89_MCC_PLAN_NO_BT:
2004 		ret = __mcc_fw_add_role(rtwdev, ref);
2005 		if (ret)
2006 			return ret;
2007 		ret = __mcc_fw_add_role(rtwdev, aux);
2008 		if (ret)
2009 			return ret;
2010 
2011 		req.btc_in_group = false;
2012 		break;
2013 	default:
2014 		rtw89_warn(rtwdev, "MCC unknown plan: %d\n", pattern->plan);
2015 		return -EFAULT;
2016 	}
2017 
2018 	if (sync->enable) {
2019 		ret = rtw89_fw_h2c_mcc_sync(rtwdev, req.group, sync->macid_src,
2020 					    sync->macid_tgt, sync->offset);
2021 		if (ret) {
2022 			rtw89_debug(rtwdev, RTW89_DBG_CHAN,
2023 				    "MCC h2c failed to trigger sync: %d\n", ret);
2024 			return ret;
2025 		}
2026 	}
2027 
2028 	req.macid = ref->rtwvif_link->mac_id;
2029 	req.tsf_high = config->start_tsf >> 32;
2030 	req.tsf_low = config->start_tsf;
2031 
2032 	ret = rtw89_fw_h2c_start_mcc(rtwdev, &req);
2033 	if (ret) {
2034 		rtw89_debug(rtwdev, RTW89_DBG_CHAN,
2035 			    "MCC h2c failed to trigger start: %d\n", ret);
2036 		return ret;
2037 	}
2038 
2039 	return 0;
2040 }
2041 
2042 static void __mrc_fw_add_courtesy(struct rtw89_dev *rtwdev,
2043 				  struct rtw89_fw_mrc_add_arg *arg)
2044 {
2045 	struct rtw89_mcc_info *mcc = &rtwdev->mcc;
2046 	struct rtw89_mcc_role *ref = &mcc->role_ref;
2047 	struct rtw89_mcc_role *aux = &mcc->role_aux;
2048 	struct rtw89_fw_mrc_add_slot_arg *slot_arg_src;
2049 
2050 	if (ref->crtz) {
2051 		slot_arg_src = &arg->slots[ref->slot_idx];
2052 
2053 		slot_arg_src->courtesy_target = aux->slot_idx;
2054 		slot_arg_src->courtesy_period = ref->crtz->slot_num;
2055 		slot_arg_src->courtesy_en = true;
2056 	}
2057 
2058 	if (aux->crtz) {
2059 		slot_arg_src = &arg->slots[aux->slot_idx];
2060 
2061 		slot_arg_src->courtesy_target = ref->slot_idx;
2062 		slot_arg_src->courtesy_period = aux->crtz->slot_num;
2063 		slot_arg_src->courtesy_en = true;
2064 	}
2065 }
2066 
2067 static int __mrc_fw_start(struct rtw89_dev *rtwdev, bool replace)
2068 {
2069 	struct rtw89_mcc_info *mcc = &rtwdev->mcc;
2070 	struct rtw89_mcc_role *ref = &mcc->role_ref;
2071 	struct rtw89_mcc_role *aux = &mcc->role_aux;
2072 	struct rtw89_mcc_config *config = &mcc->config;
2073 	struct rtw89_mcc_pattern *pattern = &config->pattern;
2074 	struct rtw89_mcc_sync *sync = &config->sync;
2075 	struct rtw89_fw_mrc_start_arg start_arg = {};
2076 	struct rtw89_fw_mrc_add_arg add_arg = {};
2077 	int ret;
2078 
2079 	BUILD_BUG_ON(RTW89_MAC_MRC_MAX_ADD_SLOT_NUM <
2080 		     NUM_OF_RTW89_MCC_ROLES + 1 /* bt role */);
2081 
2082 	if (replace) {
2083 		start_arg.old_sch_idx = mcc->group;
2084 		start_arg.action = RTW89_H2C_MRC_START_ACTION_REPLACE_OLD;
2085 		mcc->group = RTW89_MCC_NEXT_GROUP(mcc->group);
2086 	}
2087 
2088 	add_arg.sch_idx = mcc->group;
2089 	add_arg.sch_type = RTW89_H2C_MRC_SCH_BAND0_ONLY;
2090 
2091 	switch (pattern->plan) {
2092 	case RTW89_MCC_PLAN_TAIL_BT:
2093 		__mrc_fw_add_role(rtwdev, ref, &add_arg, 0);
2094 		__mrc_fw_add_role(rtwdev, aux, &add_arg, 1);
2095 		__mrc_fw_add_bt_role(rtwdev, &add_arg, 2);
2096 
2097 		add_arg.slot_num = 3;
2098 		add_arg.btc_in_sch = true;
2099 		break;
2100 	case RTW89_MCC_PLAN_MID_BT:
2101 		__mrc_fw_add_role(rtwdev, ref, &add_arg, 0);
2102 		__mrc_fw_add_bt_role(rtwdev, &add_arg, 1);
2103 		__mrc_fw_add_role(rtwdev, aux, &add_arg, 2);
2104 
2105 		add_arg.slot_num = 3;
2106 		add_arg.btc_in_sch = true;
2107 		break;
2108 	case RTW89_MCC_PLAN_NO_BT:
2109 		__mrc_fw_add_role(rtwdev, ref, &add_arg, 0);
2110 		__mrc_fw_add_role(rtwdev, aux, &add_arg, 1);
2111 
2112 		add_arg.slot_num = 2;
2113 		add_arg.btc_in_sch = false;
2114 		break;
2115 	default:
2116 		rtw89_warn(rtwdev, "MCC unknown plan: %d\n", pattern->plan);
2117 		return -EFAULT;
2118 	}
2119 
2120 	__mrc_fw_add_courtesy(rtwdev, &add_arg);
2121 
2122 	ret = rtw89_fw_h2c_mrc_add(rtwdev, &add_arg);
2123 	if (ret) {
2124 		rtw89_debug(rtwdev, RTW89_DBG_CHAN,
2125 			    "MRC h2c failed to trigger add: %d\n", ret);
2126 		return ret;
2127 	}
2128 
2129 	if (sync->enable) {
2130 		struct rtw89_fw_mrc_sync_arg sync_arg = {
2131 			.offset = sync->offset,
2132 			.src = {
2133 				.band = sync->band_src,
2134 				.port = sync->port_src,
2135 			},
2136 			.dest = {
2137 				.band = sync->band_tgt,
2138 				.port = sync->port_tgt,
2139 			},
2140 		};
2141 
2142 		ret = rtw89_fw_h2c_mrc_sync(rtwdev, &sync_arg);
2143 		if (ret) {
2144 			rtw89_debug(rtwdev, RTW89_DBG_CHAN,
2145 				    "MRC h2c failed to trigger sync: %d\n", ret);
2146 			return ret;
2147 		}
2148 	}
2149 
2150 	start_arg.sch_idx = mcc->group;
2151 	start_arg.start_tsf = config->start_tsf;
2152 
2153 	ret = rtw89_fw_h2c_mrc_start(rtwdev, &start_arg);
2154 	if (ret) {
2155 		rtw89_debug(rtwdev, RTW89_DBG_CHAN,
2156 			    "MRC h2c failed to trigger start: %d\n", ret);
2157 		return ret;
2158 	}
2159 
2160 	return 0;
2161 }
2162 
2163 static int __mcc_fw_set_duration_no_bt(struct rtw89_dev *rtwdev, bool sync_changed)
2164 {
2165 	struct rtw89_mcc_info *mcc = &rtwdev->mcc;
2166 	struct rtw89_mcc_config *config = &mcc->config;
2167 	struct rtw89_mcc_sync *sync = &config->sync;
2168 	struct rtw89_mcc_role *ref = &mcc->role_ref;
2169 	struct rtw89_mcc_role *aux = &mcc->role_aux;
2170 	struct rtw89_fw_mcc_duration req = {
2171 		.group = mcc->group,
2172 		.btc_in_group = false,
2173 		.start_macid = ref->rtwvif_link->mac_id,
2174 		.macid_x = ref->rtwvif_link->mac_id,
2175 		.macid_y = aux->rtwvif_link->mac_id,
2176 		.duration_x = ref->duration,
2177 		.duration_y = aux->duration,
2178 		.start_tsf_high = config->start_tsf >> 32,
2179 		.start_tsf_low = config->start_tsf,
2180 	};
2181 	int ret;
2182 
2183 	ret = rtw89_fw_h2c_mcc_set_duration(rtwdev, &req);
2184 	if (ret) {
2185 		rtw89_debug(rtwdev, RTW89_DBG_CHAN,
2186 			    "MCC h2c failed to set duration: %d\n", ret);
2187 		return ret;
2188 	}
2189 
2190 	if (!sync->enable || !sync_changed)
2191 		return 0;
2192 
2193 	ret = rtw89_fw_h2c_mcc_sync(rtwdev, mcc->group, sync->macid_src,
2194 				    sync->macid_tgt, sync->offset);
2195 	if (ret) {
2196 		rtw89_debug(rtwdev, RTW89_DBG_CHAN,
2197 			    "MCC h2c failed to trigger sync: %d\n", ret);
2198 		return ret;
2199 	}
2200 
2201 	return 0;
2202 }
2203 
2204 static int __mrc_fw_set_duration_no_bt(struct rtw89_dev *rtwdev, bool sync_changed)
2205 {
2206 	struct rtw89_mcc_info *mcc = &rtwdev->mcc;
2207 	struct rtw89_mcc_config *config = &mcc->config;
2208 	struct rtw89_mcc_sync *sync = &config->sync;
2209 	struct rtw89_mcc_role *ref = &mcc->role_ref;
2210 	struct rtw89_mcc_role *aux = &mcc->role_aux;
2211 	struct rtw89_fw_mrc_upd_duration_arg dur_arg = {
2212 		.sch_idx = mcc->group,
2213 		.start_tsf = config->start_tsf,
2214 		.slot_num = 2,
2215 		.slots[0] = {
2216 			.slot_idx = ref->slot_idx,
2217 			.duration = ref->duration,
2218 		},
2219 		.slots[1] = {
2220 			.slot_idx = aux->slot_idx,
2221 			.duration = aux->duration,
2222 		},
2223 	};
2224 	struct rtw89_fw_mrc_sync_arg sync_arg = {
2225 		.offset = sync->offset,
2226 		.src = {
2227 			.band = sync->band_src,
2228 			.port = sync->port_src,
2229 		},
2230 		.dest = {
2231 			.band = sync->band_tgt,
2232 			.port = sync->port_tgt,
2233 		},
2234 
2235 	};
2236 	int ret;
2237 
2238 	ret = rtw89_fw_h2c_mrc_upd_duration(rtwdev, &dur_arg);
2239 	if (ret) {
2240 		rtw89_debug(rtwdev, RTW89_DBG_CHAN,
2241 			    "MRC h2c failed to update duration: %d\n", ret);
2242 		return ret;
2243 	}
2244 
2245 	if (!sync->enable || !sync_changed)
2246 		return 0;
2247 
2248 	ret = rtw89_fw_h2c_mrc_sync(rtwdev, &sync_arg);
2249 	if (ret) {
2250 		rtw89_debug(rtwdev, RTW89_DBG_CHAN,
2251 			    "MRC h2c failed to trigger sync: %d\n", ret);
2252 		return ret;
2253 	}
2254 
2255 	return 0;
2256 }
2257 
2258 static void rtw89_mcc_handle_beacon_noa(struct rtw89_dev *rtwdev, bool enable)
2259 {
2260 	struct rtw89_mcc_info *mcc = &rtwdev->mcc;
2261 	struct rtw89_mcc_role *ref = &mcc->role_ref;
2262 	struct rtw89_mcc_role *aux = &mcc->role_aux;
2263 	struct rtw89_mcc_config *config = &mcc->config;
2264 	struct ieee80211_p2p_noa_desc noa_desc = {};
2265 	u32 interval = config->mcc_interval;
2266 	struct rtw89_vif_link *rtwvif_go;
2267 	u64 start_time;
2268 	u32 duration;
2269 
2270 	if (mcc->mode != RTW89_MCC_MODE_GO_STA)
2271 		return;
2272 
2273 	if (ref->is_go) {
2274 		start_time = config->start_tsf;
2275 		rtwvif_go = ref->rtwvif_link;
2276 		start_time += ieee80211_tu_to_usec(ref->duration);
2277 		duration = config->mcc_interval - ref->duration;
2278 	} else if (aux->is_go) {
2279 		start_time = config->start_tsf_in_aux_domain;
2280 		rtwvif_go = aux->rtwvif_link;
2281 		duration = config->mcc_interval - aux->duration;
2282 	} else {
2283 		rtw89_debug(rtwdev, RTW89_DBG_CHAN,
2284 			    "MCC find no GO: skip updating beacon NoA\n");
2285 		return;
2286 	}
2287 
2288 	rtw89_p2p_noa_renew(rtwvif_go);
2289 
2290 	if (enable) {
2291 		duration += RTW89_MCC_SWITCH_CH_TIME;
2292 		noa_desc.start_time = cpu_to_le32(start_time);
2293 		noa_desc.interval = cpu_to_le32(ieee80211_tu_to_usec(interval));
2294 		noa_desc.duration = cpu_to_le32(ieee80211_tu_to_usec(duration));
2295 		noa_desc.count = 255;
2296 		rtw89_p2p_noa_append(rtwvif_go, &noa_desc);
2297 	}
2298 
2299 	/* without chanctx, we cannot get beacon from mac80211 stack */
2300 	if (!rtwvif_go->chanctx_assigned)
2301 		return;
2302 
2303 	rtw89_chip_h2c_update_beacon(rtwdev, rtwvif_go);
2304 }
2305 
2306 static void rtw89_mcc_start_beacon_noa(struct rtw89_dev *rtwdev)
2307 {
2308 	struct rtw89_mcc_info *mcc = &rtwdev->mcc;
2309 	struct rtw89_mcc_role *ref = &mcc->role_ref;
2310 	struct rtw89_mcc_role *aux = &mcc->role_aux;
2311 
2312 	if (mcc->mode != RTW89_MCC_MODE_GO_STA)
2313 		return;
2314 
2315 	if (ref->is_go)
2316 		rtw89_fw_h2c_tsf32_toggle(rtwdev, ref->rtwvif_link, true);
2317 	else if (aux->is_go)
2318 		rtw89_fw_h2c_tsf32_toggle(rtwdev, aux->rtwvif_link, true);
2319 
2320 	rtw89_mcc_handle_beacon_noa(rtwdev, true);
2321 }
2322 
2323 static void rtw89_mcc_stop_beacon_noa(struct rtw89_dev *rtwdev)
2324 {
2325 	struct rtw89_mcc_info *mcc = &rtwdev->mcc;
2326 	struct rtw89_mcc_role *ref = &mcc->role_ref;
2327 	struct rtw89_mcc_role *aux = &mcc->role_aux;
2328 
2329 	if (mcc->mode != RTW89_MCC_MODE_GO_STA)
2330 		return;
2331 
2332 	if (ref->is_go)
2333 		rtw89_fw_h2c_tsf32_toggle(rtwdev, ref->rtwvif_link, false);
2334 	else if (aux->is_go)
2335 		rtw89_fw_h2c_tsf32_toggle(rtwdev, aux->rtwvif_link, false);
2336 
2337 	rtw89_mcc_handle_beacon_noa(rtwdev, false);
2338 }
2339 
2340 static bool rtw89_mcc_ignore_bcn(struct rtw89_dev *rtwdev, struct rtw89_mcc_role *role)
2341 {
2342 	enum rtw89_chip_gen chip_gen = rtwdev->chip->chip_gen;
2343 
2344 	if (role->is_go)
2345 		return true;
2346 	else if (chip_gen == RTW89_CHIP_BE && role->is_gc)
2347 		return true;
2348 	else
2349 		return false;
2350 }
2351 
2352 static int rtw89_mcc_start(struct rtw89_dev *rtwdev)
2353 {
2354 	struct rtw89_mcc_info *mcc = &rtwdev->mcc;
2355 	struct rtw89_mcc_role *ref = &mcc->role_ref;
2356 	struct rtw89_mcc_role *aux = &mcc->role_aux;
2357 	int ret;
2358 
2359 	if (rtwdev->scanning)
2360 		rtw89_hw_scan_abort(rtwdev, rtwdev->scan_info.scanning_vif);
2361 
2362 	rtw89_leave_lps(rtwdev);
2363 
2364 	rtw89_debug(rtwdev, RTW89_DBG_CHAN, "MCC start\n");
2365 
2366 	ret = rtw89_mcc_fill_all_roles(rtwdev);
2367 	if (ret)
2368 		return ret;
2369 
2370 	if (ref->is_go || aux->is_go)
2371 		mcc->mode = RTW89_MCC_MODE_GO_STA;
2372 	else
2373 		mcc->mode = RTW89_MCC_MODE_GC_STA;
2374 
2375 	rtw89_debug(rtwdev, RTW89_DBG_CHAN, "MCC sel mode: %d\n", mcc->mode);
2376 
2377 	mcc->group = RTW89_MCC_DFLT_GROUP;
2378 
2379 	ret = rtw89_mcc_fill_config(rtwdev);
2380 	if (ret)
2381 		return ret;
2382 
2383 	if (rtw89_mcc_ignore_bcn(rtwdev, ref) || aux->ignore_bcn) {
2384 		rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, aux->rtwvif_link, false);
2385 	} else if (rtw89_mcc_ignore_bcn(rtwdev, aux) || ref->ignore_bcn) {
2386 		rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, ref->rtwvif_link, false);
2387 	} else {
2388 		rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, ref->rtwvif_link, true);
2389 		rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, aux->rtwvif_link, true);
2390 	}
2391 
2392 	if (rtw89_concurrent_via_mrc(rtwdev))
2393 		ret = __mrc_fw_start(rtwdev, false);
2394 	else
2395 		ret = __mcc_fw_start(rtwdev, false);
2396 
2397 	if (ret)
2398 		return ret;
2399 
2400 	rtw89_chanctx_notify(rtwdev, RTW89_CHANCTX_STATE_MCC_START);
2401 
2402 	rtw89_mcc_start_beacon_noa(rtwdev);
2403 	rtw89_phy_dig_suspend(rtwdev);
2404 
2405 	rtw89_mcc_prepare(rtwdev, true);
2406 	return 0;
2407 }
2408 
2409 struct rtw89_mcc_stop_sel {
2410 	struct {
2411 		const struct rtw89_vif_link *target;
2412 	} hint;
2413 
2414 	/* selection content */
2415 	bool filled;
2416 	u8 mac_id;
2417 	u8 slot_idx;
2418 };
2419 
2420 static void rtw89_mcc_stop_sel_fill(struct rtw89_mcc_stop_sel *sel,
2421 				    const struct rtw89_mcc_role *mcc_role)
2422 {
2423 	sel->mac_id = mcc_role->rtwvif_link->mac_id;
2424 	sel->slot_idx = mcc_role->slot_idx;
2425 	sel->filled = true;
2426 }
2427 
2428 static int rtw89_mcc_stop_sel_iterator(struct rtw89_dev *rtwdev,
2429 				       struct rtw89_mcc_role *mcc_role,
2430 				       unsigned int ordered_idx,
2431 				       void *data)
2432 {
2433 	struct rtw89_mcc_stop_sel *sel = data;
2434 
2435 	if (mcc_role->rtwvif_link == sel->hint.target) {
2436 		rtw89_mcc_stop_sel_fill(sel, mcc_role);
2437 		return 1; /* break iteration */
2438 	}
2439 
2440 	if (sel->filled)
2441 		return 0;
2442 
2443 	if (!mcc_role->rtwvif_link->chanctx_assigned)
2444 		return 0;
2445 
2446 	rtw89_mcc_stop_sel_fill(sel, mcc_role);
2447 	return 0;
2448 }
2449 
2450 static void rtw89_mcc_stop(struct rtw89_dev *rtwdev,
2451 			   const struct rtw89_chanctx_pause_parm *pause)
2452 {
2453 	struct rtw89_hal *hal = &rtwdev->hal;
2454 	struct rtw89_mcc_info *mcc = &rtwdev->mcc;
2455 	struct rtw89_mcc_role *ref = &mcc->role_ref;
2456 	struct rtw89_mcc_role *aux = &mcc->role_aux;
2457 	struct rtw89_mcc_stop_sel sel = {
2458 		.hint.target = pause ? pause->trigger : NULL,
2459 	};
2460 	bool rsn_scan;
2461 	int ret;
2462 
2463 	if (!pause) {
2464 		wiphy_delayed_work_cancel(rtwdev->hw->wiphy, &rtwdev->chanctx_work);
2465 		bitmap_zero(hal->changes, NUM_OF_RTW89_CHANCTX_CHANGES);
2466 	}
2467 
2468 	rsn_scan = pause && pause->rsn == RTW89_CHANCTX_PAUSE_REASON_HW_SCAN;
2469 	if (rsn_scan && ref->is_go)
2470 		sel.hint.target = ref->rtwvif_link;
2471 	else if (rsn_scan && aux->is_go)
2472 		sel.hint.target = aux->rtwvif_link;
2473 
2474 	/* by default, stop at ref */
2475 	rtw89_iterate_mcc_roles(rtwdev, rtw89_mcc_stop_sel_iterator, &sel);
2476 	if (!sel.filled)
2477 		rtw89_mcc_stop_sel_fill(&sel, ref);
2478 
2479 	rtw89_debug(rtwdev, RTW89_DBG_CHAN, "MCC stop at <macid %d>\n", sel.mac_id);
2480 
2481 	if (rtw89_concurrent_via_mrc(rtwdev)) {
2482 		ret = rtw89_fw_h2c_mrc_del(rtwdev, mcc->group, sel.slot_idx);
2483 		if (ret)
2484 			rtw89_debug(rtwdev, RTW89_DBG_CHAN,
2485 				    "MRC h2c failed to trigger del: %d\n", ret);
2486 	} else {
2487 		ret = rtw89_fw_h2c_stop_mcc(rtwdev, mcc->group,
2488 					    sel.mac_id, true);
2489 		if (ret)
2490 			rtw89_debug(rtwdev, RTW89_DBG_CHAN,
2491 				    "MCC h2c failed to trigger stop: %d\n", ret);
2492 
2493 		ret = rtw89_fw_h2c_del_mcc_group(rtwdev, mcc->group, true);
2494 		if (ret)
2495 			rtw89_debug(rtwdev, RTW89_DBG_CHAN,
2496 				    "MCC h2c failed to delete group: %d\n", ret);
2497 	}
2498 
2499 	rtw89_chanctx_notify(rtwdev, RTW89_CHANCTX_STATE_MCC_STOP);
2500 
2501 	rtw89_mcc_stop_beacon_noa(rtwdev);
2502 	rtw89_fw_h2c_mcc_dig(rtwdev, RTW89_CHANCTX_0, 0, 0, false);
2503 	rtw89_phy_dig_resume(rtwdev, true);
2504 
2505 	rtw89_mcc_prepare(rtwdev, false);
2506 }
2507 
2508 static int rtw89_mcc_update(struct rtw89_dev *rtwdev)
2509 {
2510 	struct rtw89_mcc_info *mcc = &rtwdev->mcc;
2511 	bool old_ref_ignore_bcn = mcc->role_ref.ignore_bcn;
2512 	bool old_aux_ignore_bcn = mcc->role_aux.ignore_bcn;
2513 	struct rtw89_mcc_config *config = &mcc->config;
2514 	struct rtw89_mcc_role *ref = &mcc->role_ref;
2515 	struct rtw89_mcc_role *aux = &mcc->role_aux;
2516 	struct rtw89_mcc_config old_cfg = *config;
2517 	bool courtesy_changed;
2518 	bool sync_changed;
2519 	int ret;
2520 
2521 	if (rtwdev->scanning)
2522 		rtw89_hw_scan_abort(rtwdev, rtwdev->scan_info.scanning_vif);
2523 
2524 	rtw89_debug(rtwdev, RTW89_DBG_CHAN, "MCC update\n");
2525 
2526 	ret = rtw89_mcc_fill_config(rtwdev);
2527 	if (ret)
2528 		return ret;
2529 
2530 	if (old_ref_ignore_bcn != ref->ignore_bcn)
2531 		rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, ref->rtwvif_link, !ref->ignore_bcn);
2532 	else if (old_aux_ignore_bcn != aux->ignore_bcn)
2533 		rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, aux->rtwvif_link, !aux->ignore_bcn);
2534 
2535 	if (memcmp(&old_cfg.pattern.courtesy, &config->pattern.courtesy,
2536 		   sizeof(old_cfg.pattern.courtesy)) == 0)
2537 		courtesy_changed = false;
2538 	else
2539 		courtesy_changed = true;
2540 
2541 	if (old_cfg.pattern.plan != RTW89_MCC_PLAN_NO_BT ||
2542 	    config->pattern.plan != RTW89_MCC_PLAN_NO_BT ||
2543 	    courtesy_changed) {
2544 		if (rtw89_concurrent_via_mrc(rtwdev))
2545 			ret = __mrc_fw_start(rtwdev, true);
2546 		else
2547 			ret = __mcc_fw_start(rtwdev, true);
2548 
2549 		if (ret)
2550 			return ret;
2551 	} else {
2552 		if (memcmp(&old_cfg.sync, &config->sync, sizeof(old_cfg.sync)) == 0)
2553 			sync_changed = false;
2554 		else
2555 			sync_changed = true;
2556 
2557 		if (rtw89_concurrent_via_mrc(rtwdev))
2558 			ret = __mrc_fw_set_duration_no_bt(rtwdev, sync_changed);
2559 		else
2560 			ret = __mcc_fw_set_duration_no_bt(rtwdev, sync_changed);
2561 
2562 		if (ret)
2563 			return ret;
2564 	}
2565 
2566 	rtw89_mcc_handle_beacon_noa(rtwdev, true);
2567 	return 0;
2568 }
2569 
2570 static int rtw89_mcc_search_gc_iterator(struct rtw89_dev *rtwdev,
2571 					struct rtw89_mcc_role *mcc_role,
2572 					unsigned int ordered_idx,
2573 					void *data)
2574 {
2575 	struct rtw89_mcc_role **role = data;
2576 
2577 	if (mcc_role->is_gc)
2578 		*role = mcc_role;
2579 
2580 	return 0;
2581 }
2582 
2583 static struct rtw89_mcc_role *rtw89_mcc_get_gc_role(struct rtw89_dev *rtwdev)
2584 {
2585 	struct rtw89_mcc_info *mcc = &rtwdev->mcc;
2586 	struct rtw89_mcc_role *role = NULL;
2587 
2588 	if (mcc->mode != RTW89_MCC_MODE_GC_STA)
2589 		return NULL;
2590 
2591 	rtw89_iterate_mcc_roles(rtwdev, rtw89_mcc_search_gc_iterator, &role);
2592 
2593 	return role;
2594 }
2595 
2596 void rtw89_mcc_gc_detect_beacon_work(struct wiphy *wiphy, struct wiphy_work *work)
2597 {
2598 	struct rtw89_vif_link *rtwvif_link = container_of(work, struct rtw89_vif_link,
2599 							  mcc_gc_detect_beacon_work.work);
2600 	struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link);
2601 	enum rtw89_entity_mode mode;
2602 	struct rtw89_dev *rtwdev;
2603 
2604 	lockdep_assert_wiphy(wiphy);
2605 
2606 	rtwdev = rtwvif_link->rtwvif->rtwdev;
2607 
2608 	mode = rtw89_get_entity_mode(rtwdev);
2609 	if (mode != RTW89_ENTITY_MODE_MCC)
2610 		return;
2611 
2612 	if (READ_ONCE(rtwvif_link->sync_bcn_tsf) > rtwvif_link->last_sync_bcn_tsf)
2613 		rtwvif_link->detect_bcn_count = 0;
2614 	else
2615 		rtwvif_link->detect_bcn_count++;
2616 
2617 	if (rtwvif_link->detect_bcn_count < RTW89_MCC_DETECT_BCN_MAX_TRIES)
2618 		rtw89_chanctx_proceed(rtwdev, NULL);
2619 	else
2620 		ieee80211_connection_loss(vif);
2621 }
2622 
2623 bool rtw89_mcc_detect_go_bcn(struct rtw89_dev *rtwdev,
2624 			     struct rtw89_vif_link *rtwvif_link)
2625 {
2626 	enum rtw89_entity_mode mode = rtw89_get_entity_mode(rtwdev);
2627 	struct rtw89_chanctx_pause_parm pause_parm = {
2628 		.rsn = RTW89_CHANCTX_PAUSE_REASON_GC_BCN_LOSS,
2629 		.trigger = rtwvif_link,
2630 	};
2631 	struct ieee80211_bss_conf *bss_conf;
2632 	struct rtw89_mcc_role *role;
2633 	u16 bcn_int;
2634 
2635 	if (mode != RTW89_ENTITY_MODE_MCC)
2636 		return false;
2637 
2638 	role = rtw89_mcc_get_gc_role(rtwdev);
2639 	if (!role)
2640 		return false;
2641 
2642 	if (role->rtwvif_link != rtwvif_link)
2643 		return false;
2644 
2645 	rtw89_debug(rtwdev, RTW89_DBG_CHAN,
2646 		    "MCC GC beacon loss, pause MCC to detect GO beacon\n");
2647 
2648 	rcu_read_lock();
2649 
2650 	bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true);
2651 	bcn_int = bss_conf->beacon_int;
2652 
2653 	rcu_read_unlock();
2654 
2655 	rtw89_chanctx_pause(rtwdev, &pause_parm);
2656 	rtwvif_link->last_sync_bcn_tsf = READ_ONCE(rtwvif_link->sync_bcn_tsf);
2657 	wiphy_delayed_work_queue(rtwdev->hw->wiphy,
2658 				 &rtwvif_link->mcc_gc_detect_beacon_work,
2659 				 usecs_to_jiffies(ieee80211_tu_to_usec(bcn_int)));
2660 
2661 	return true;
2662 }
2663 
2664 static void rtw89_mcc_detect_connection(struct rtw89_dev *rtwdev,
2665 					struct rtw89_mcc_role *role)
2666 {
2667 	struct rtw89_vif_link *rtwvif_link = role->rtwvif_link;
2668 	struct ieee80211_vif *vif;
2669 	bool start_detect;
2670 	int ret;
2671 
2672 	ret = rtw89_core_send_nullfunc(rtwdev, role->rtwvif_link, true, false,
2673 				       RTW89_MCC_PROBE_TIMEOUT);
2674 	if (ret &&
2675 	    READ_ONCE(rtwvif_link->sync_bcn_tsf) == rtwvif_link->last_sync_bcn_tsf)
2676 		role->probe_count++;
2677 	else
2678 		role->probe_count = 0;
2679 
2680 	rtwvif_link->last_sync_bcn_tsf = READ_ONCE(rtwvif_link->sync_bcn_tsf);
2681 	if (role->probe_count < RTW89_MCC_PROBE_MAX_TRIES)
2682 		return;
2683 
2684 	rtw89_debug(rtwdev, RTW89_DBG_CHAN,
2685 		    "MCC <macid %d> can not detect AP/GO\n", role->rtwvif_link->mac_id);
2686 
2687 	start_detect = rtw89_mcc_detect_go_bcn(rtwdev, role->rtwvif_link);
2688 	if (start_detect)
2689 		return;
2690 
2691 	vif = rtwvif_link_to_vif(role->rtwvif_link);
2692 	ieee80211_connection_loss(vif);
2693 }
2694 
2695 static void rtw89_mcc_track(struct rtw89_dev *rtwdev)
2696 {
2697 	struct rtw89_mcc_info *mcc = &rtwdev->mcc;
2698 	struct rtw89_mcc_config *config = &mcc->config;
2699 	struct rtw89_mcc_pattern *pattern = &config->pattern;
2700 	struct rtw89_mcc_role *ref = &mcc->role_ref;
2701 	struct rtw89_mcc_role *aux = &mcc->role_aux;
2702 	u16 tolerance;
2703 	u16 bcn_ofst;
2704 	u16 diff;
2705 
2706 	if (rtw89_mcc_ignore_bcn(rtwdev, ref) || aux->ignore_bcn)
2707 		rtw89_mcc_detect_connection(rtwdev, aux);
2708 	else if (rtw89_mcc_ignore_bcn(rtwdev, aux) || ref->ignore_bcn)
2709 		rtw89_mcc_detect_connection(rtwdev, ref);
2710 
2711 	if (mcc->mode != RTW89_MCC_MODE_GC_STA)
2712 		return;
2713 
2714 	bcn_ofst = rtw89_mcc_get_bcn_ofst(rtwdev);
2715 	if (bcn_ofst == config->beacon_offset)
2716 		return;
2717 
2718 	if (bcn_ofst > config->beacon_offset) {
2719 		diff = bcn_ofst - config->beacon_offset;
2720 		if (pattern->tob_aux < 0)
2721 			tolerance = -pattern->tob_aux;
2722 		else if (pattern->toa_aux > 0)
2723 			tolerance = pattern->toa_aux;
2724 		else
2725 			return; /* no chance to improve */
2726 	} else {
2727 		diff = config->beacon_offset - bcn_ofst;
2728 		if (pattern->toa_aux < 0)
2729 			tolerance = -pattern->toa_aux;
2730 		else if (pattern->tob_aux > 0)
2731 			tolerance = pattern->tob_aux;
2732 		else
2733 			return; /* no chance to improve */
2734 	}
2735 
2736 	if (diff <= tolerance)
2737 		return;
2738 
2739 	rtw89_queue_chanctx_change(rtwdev, RTW89_CHANCTX_BCN_OFFSET_CHANGE);
2740 }
2741 
2742 static int __mcc_fw_upd_macid_bitmap(struct rtw89_dev *rtwdev,
2743 				     struct rtw89_mcc_role *upd)
2744 {
2745 	struct rtw89_mcc_info *mcc = &rtwdev->mcc;
2746 	int ret;
2747 
2748 	ret = rtw89_fw_h2c_mcc_macid_bitmap(rtwdev, mcc->group,
2749 					    upd->rtwvif_link->mac_id,
2750 					    upd->macid_bitmap);
2751 	if (ret) {
2752 		rtw89_debug(rtwdev, RTW89_DBG_CHAN,
2753 			    "MCC h2c failed to update macid bitmap: %d\n", ret);
2754 		return ret;
2755 	}
2756 
2757 	return 0;
2758 }
2759 
2760 static int __mrc_fw_upd_macid_bitmap(struct rtw89_dev *rtwdev,
2761 				     struct rtw89_mcc_role *cur,
2762 				     struct rtw89_mcc_role *upd)
2763 {
2764 	struct rtw89_mcc_info *mcc = &rtwdev->mcc;
2765 	struct rtw89_fw_mrc_upd_bitmap_arg arg = {};
2766 	u32 old = rtw89_mcc_role_fw_macid_bitmap_to_u32(cur);
2767 	u32 new = rtw89_mcc_role_fw_macid_bitmap_to_u32(upd);
2768 	u32 add = new & ~old;
2769 	u32 del = old & ~new;
2770 	int ret;
2771 	int i;
2772 
2773 	arg.sch_idx = mcc->group;
2774 	arg.macid = upd->rtwvif_link->mac_id;
2775 
2776 	for (i = 0; i < 32; i++) {
2777 		if (add & BIT(i)) {
2778 			arg.client_macid = i;
2779 			arg.action = RTW89_H2C_MRC_UPD_BITMAP_ACTION_ADD;
2780 
2781 			ret = rtw89_fw_h2c_mrc_upd_bitmap(rtwdev, &arg);
2782 			if (ret)
2783 				goto err;
2784 		}
2785 	}
2786 
2787 	for (i = 0; i < 32; i++) {
2788 		if (del & BIT(i)) {
2789 			arg.client_macid = i;
2790 			arg.action = RTW89_H2C_MRC_UPD_BITMAP_ACTION_DEL;
2791 
2792 			ret = rtw89_fw_h2c_mrc_upd_bitmap(rtwdev, &arg);
2793 			if (ret)
2794 				goto err;
2795 		}
2796 	}
2797 
2798 	return 0;
2799 
2800 err:
2801 	rtw89_debug(rtwdev, RTW89_DBG_CHAN,
2802 		    "MRC h2c failed to update bitmap: %d\n", ret);
2803 	return ret;
2804 }
2805 
2806 static int rtw89_mcc_upd_map_iterator(struct rtw89_dev *rtwdev,
2807 				      struct rtw89_mcc_role *mcc_role,
2808 				      unsigned int ordered_idx,
2809 				      void *data)
2810 {
2811 	struct rtw89_mcc_role upd = {
2812 		.rtwvif_link = mcc_role->rtwvif_link,
2813 	};
2814 	int ret;
2815 
2816 	if (!mcc_role->is_go)
2817 		return 0;
2818 
2819 	rtw89_mcc_fill_role_macid_bitmap(rtwdev, &upd);
2820 	if (memcmp(mcc_role->macid_bitmap, upd.macid_bitmap,
2821 		   sizeof(mcc_role->macid_bitmap)) == 0)
2822 		return 0;
2823 
2824 	if (rtw89_concurrent_via_mrc(rtwdev))
2825 		ret = __mrc_fw_upd_macid_bitmap(rtwdev, mcc_role, &upd);
2826 	else
2827 		ret = __mcc_fw_upd_macid_bitmap(rtwdev, &upd);
2828 
2829 	if (ret)
2830 		return ret;
2831 
2832 	memcpy(mcc_role->macid_bitmap, upd.macid_bitmap,
2833 	       sizeof(mcc_role->macid_bitmap));
2834 	return 0;
2835 }
2836 
2837 static void rtw89_mcc_update_macid_bitmap(struct rtw89_dev *rtwdev)
2838 {
2839 	struct rtw89_mcc_info *mcc = &rtwdev->mcc;
2840 
2841 	if (mcc->mode != RTW89_MCC_MODE_GO_STA)
2842 		return;
2843 
2844 	rtw89_iterate_mcc_roles(rtwdev, rtw89_mcc_upd_map_iterator, NULL);
2845 }
2846 
2847 static int rtw89_mcc_upd_lmt_iterator(struct rtw89_dev *rtwdev,
2848 				      struct rtw89_mcc_role *mcc_role,
2849 				      unsigned int ordered_idx,
2850 				      void *data)
2851 {
2852 	memset(&mcc_role->limit, 0, sizeof(mcc_role->limit));
2853 	rtw89_mcc_fill_role_limit(rtwdev, mcc_role);
2854 	return 0;
2855 }
2856 
2857 static void rtw89_mcc_update_limit(struct rtw89_dev *rtwdev)
2858 {
2859 	struct rtw89_mcc_info *mcc = &rtwdev->mcc;
2860 
2861 	if (mcc->mode != RTW89_MCC_MODE_GC_STA)
2862 		return;
2863 
2864 	rtw89_iterate_mcc_roles(rtwdev, rtw89_mcc_upd_lmt_iterator, NULL);
2865 }
2866 
2867 static int rtw89_mcc_get_links_iterator(struct rtw89_dev *rtwdev,
2868 					struct rtw89_mcc_role *mcc_role,
2869 					unsigned int ordered_idx,
2870 					void *data)
2871 {
2872 	struct rtw89_mcc_links_info *info = data;
2873 
2874 	info->links[ordered_idx] = mcc_role->rtwvif_link;
2875 	return 0;
2876 }
2877 
2878 void rtw89_mcc_get_links(struct rtw89_dev *rtwdev, struct rtw89_mcc_links_info *info)
2879 {
2880 	enum rtw89_entity_mode mode;
2881 
2882 	memset(info, 0, sizeof(*info));
2883 
2884 	mode = rtw89_get_entity_mode(rtwdev);
2885 	if (unlikely(mode != RTW89_ENTITY_MODE_MCC))
2886 		return;
2887 
2888 	rtw89_iterate_mcc_roles(rtwdev, rtw89_mcc_get_links_iterator, info);
2889 }
2890 
2891 void rtw89_chanctx_work(struct wiphy *wiphy, struct wiphy_work *work)
2892 {
2893 	struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
2894 						chanctx_work.work);
2895 	struct rtw89_hal *hal = &rtwdev->hal;
2896 	bool update_mcc_pattern = false;
2897 	enum rtw89_entity_mode mode;
2898 	u32 changed = 0;
2899 	int ret;
2900 	int i;
2901 
2902 	lockdep_assert_wiphy(wiphy);
2903 
2904 	if (hal->entity_pause)
2905 		return;
2906 
2907 	for (i = 0; i < NUM_OF_RTW89_CHANCTX_CHANGES; i++) {
2908 		if (test_and_clear_bit(i, hal->changes))
2909 			changed |= BIT(i);
2910 	}
2911 
2912 	mode = rtw89_get_entity_mode(rtwdev);
2913 	switch (mode) {
2914 	case RTW89_ENTITY_MODE_MCC_PREPARE:
2915 		rtw89_set_entity_mode(rtwdev, RTW89_ENTITY_MODE_MCC);
2916 		rtw89_set_channel(rtwdev);
2917 
2918 		ret = rtw89_mcc_start(rtwdev);
2919 		if (ret)
2920 			rtw89_warn(rtwdev, "failed to start MCC: %d\n", ret);
2921 		break;
2922 	case RTW89_ENTITY_MODE_MCC:
2923 		if (changed & BIT(RTW89_CHANCTX_BCN_OFFSET_CHANGE) ||
2924 		    changed & BIT(RTW89_CHANCTX_P2P_PS_CHANGE) ||
2925 		    changed & BIT(RTW89_CHANCTX_BT_SLOT_CHANGE) ||
2926 		    changed & BIT(RTW89_CHANCTX_TSF32_TOGGLE_CHANGE))
2927 			update_mcc_pattern = true;
2928 		if (changed & BIT(RTW89_CHANCTX_REMOTE_STA_CHANGE))
2929 			rtw89_mcc_update_macid_bitmap(rtwdev);
2930 		if (changed & BIT(RTW89_CHANCTX_P2P_PS_CHANGE))
2931 			rtw89_mcc_update_limit(rtwdev);
2932 		if (changed & BIT(RTW89_CHANCTX_BT_SLOT_CHANGE))
2933 			rtw89_mcc_fill_bt_role(rtwdev);
2934 		if (update_mcc_pattern) {
2935 			ret = rtw89_mcc_update(rtwdev);
2936 			if (ret)
2937 				rtw89_warn(rtwdev, "failed to update MCC: %d\n",
2938 					   ret);
2939 		}
2940 		break;
2941 	default:
2942 		break;
2943 	}
2944 }
2945 
2946 void rtw89_queue_chanctx_change(struct rtw89_dev *rtwdev,
2947 				enum rtw89_chanctx_changes change)
2948 {
2949 	struct rtw89_hal *hal = &rtwdev->hal;
2950 	enum rtw89_entity_mode mode;
2951 	u32 delay;
2952 
2953 	mode = rtw89_get_entity_mode(rtwdev);
2954 	switch (mode) {
2955 	default:
2956 		return;
2957 	case RTW89_ENTITY_MODE_MCC_PREPARE:
2958 		delay = ieee80211_tu_to_usec(RTW89_CHANCTX_TIME_MCC_PREPARE);
2959 		rtw89_phy_dig_suspend(rtwdev);
2960 		break;
2961 	case RTW89_ENTITY_MODE_MCC:
2962 		delay = ieee80211_tu_to_usec(RTW89_CHANCTX_TIME_MCC);
2963 		break;
2964 	}
2965 
2966 	if (change != RTW89_CHANCTX_CHANGE_DFLT) {
2967 		rtw89_debug(rtwdev, RTW89_DBG_CHAN, "set chanctx change %d\n",
2968 			    change);
2969 		set_bit(change, hal->changes);
2970 	}
2971 
2972 	rtw89_debug(rtwdev, RTW89_DBG_CHAN,
2973 		    "queue chanctx work for mode %d with delay %d us\n",
2974 		    mode, delay);
2975 	wiphy_delayed_work_queue(rtwdev->hw->wiphy, &rtwdev->chanctx_work,
2976 				 usecs_to_jiffies(delay));
2977 }
2978 
2979 void rtw89_queue_chanctx_work(struct rtw89_dev *rtwdev)
2980 {
2981 	rtw89_queue_chanctx_change(rtwdev, RTW89_CHANCTX_CHANGE_DFLT);
2982 }
2983 
2984 static enum rtw89_mr_wtype __rtw89_query_mr_wtype(struct rtw89_dev *rtwdev)
2985 {
2986 	struct rtw89_entity_mgnt *mgnt = &rtwdev->hal.entity_mgnt;
2987 	enum rtw89_chanctx_idx chanctx_idx;
2988 	struct ieee80211_vif *vif;
2989 	struct rtw89_vif *rtwvif;
2990 	unsigned int num_mld = 0;
2991 	unsigned int num_ml = 0;
2992 	unsigned int cnt = 0;
2993 	u8 role_idx;
2994 	u8 idx;
2995 
2996 	for (role_idx = 0; role_idx < RTW89_MAX_INTERFACE_NUM; role_idx++) {
2997 		rtwvif = mgnt->active_roles[role_idx];
2998 		if (!rtwvif)
2999 			continue;
3000 
3001 		cnt++;
3002 
3003 		vif = rtwvif_to_vif(rtwvif);
3004 		if (!ieee80211_vif_is_mld(vif))
3005 			continue;
3006 
3007 		num_mld++;
3008 
3009 		for (idx = 0; idx < __RTW89_MLD_MAX_LINK_NUM; idx++) {
3010 			chanctx_idx = mgnt->chanctx_tbl[role_idx][idx];
3011 			if (chanctx_idx != RTW89_CHANCTX_IDLE)
3012 				num_ml++;
3013 		}
3014 	}
3015 
3016 	if (num_mld > 1)
3017 		goto err;
3018 
3019 	switch (cnt) {
3020 	case 0:
3021 		return RTW89_MR_WTYPE_NONE;
3022 	case 1:
3023 		if (!num_mld)
3024 			return RTW89_MR_WTYPE_NONMLD;
3025 		switch (num_ml) {
3026 		case 1:
3027 			return RTW89_MR_WTYPE_MLD1L1R;
3028 		case 2:
3029 			return RTW89_MR_WTYPE_MLD2L1R;
3030 		default:
3031 			break;
3032 		}
3033 		break;
3034 	case 2:
3035 		if (!num_mld)
3036 			return RTW89_MR_WTYPE_NONMLD_NONMLD;
3037 		switch (num_ml) {
3038 		case 1:
3039 			return RTW89_MR_WTYPE_MLD1L1R_NONMLD;
3040 		case 2:
3041 			return RTW89_MR_WTYPE_MLD2L1R_NONMLD;
3042 		default:
3043 			break;
3044 		}
3045 		break;
3046 	default:
3047 		break;
3048 	}
3049 
3050 err:
3051 	rtw89_warn(rtwdev, "%s: unhandled cnt %u mld %u ml %u\n", __func__,
3052 		   cnt, num_mld, num_ml);
3053 	return RTW89_MR_WTYPE_UNKNOWN;
3054 }
3055 
3056 static enum rtw89_mr_wmode __rtw89_query_mr_wmode(struct rtw89_dev *rtwdev,
3057 						  u8 inst_idx)
3058 {
3059 	struct rtw89_entity_mgnt *mgnt = &rtwdev->hal.entity_mgnt;
3060 	unsigned int num[NUM_NL80211_IFTYPES] = {};
3061 	enum rtw89_chanctx_idx chanctx_idx;
3062 	struct ieee80211_vif *vif;
3063 	struct rtw89_vif *rtwvif;
3064 	unsigned int cnt = 0;
3065 	u8 role_idx;
3066 
3067 	if (unlikely(inst_idx >= __RTW89_MLD_MAX_LINK_NUM))
3068 		return RTW89_MR_WMODE_UNKNOWN;
3069 
3070 	for (role_idx = 0; role_idx < RTW89_MAX_INTERFACE_NUM; role_idx++) {
3071 		chanctx_idx = mgnt->chanctx_tbl[role_idx][inst_idx];
3072 		if (chanctx_idx == RTW89_CHANCTX_IDLE)
3073 			continue;
3074 
3075 		rtwvif = mgnt->active_roles[role_idx];
3076 		if (unlikely(!rtwvif))
3077 			continue;
3078 
3079 		vif = rtwvif_to_vif(rtwvif);
3080 		num[vif->type]++;
3081 		cnt++;
3082 	}
3083 
3084 	switch (cnt) {
3085 	case 0:
3086 		return RTW89_MR_WMODE_NONE;
3087 	case 1:
3088 		if (num[NL80211_IFTYPE_STATION])
3089 			return RTW89_MR_WMODE_1CLIENT;
3090 		if (num[NL80211_IFTYPE_AP])
3091 			return RTW89_MR_WMODE_1AP;
3092 		break;
3093 	case 2:
3094 		if (num[NL80211_IFTYPE_STATION] == 2)
3095 			return RTW89_MR_WMODE_2CLIENTS;
3096 		if (num[NL80211_IFTYPE_AP] == 2)
3097 			return RTW89_MR_WMODE_2APS;
3098 		if (num[NL80211_IFTYPE_STATION] && num[NL80211_IFTYPE_AP])
3099 			return RTW89_MR_WMODE_1AP_1CLIENT;
3100 		break;
3101 	default:
3102 		break;
3103 	}
3104 
3105 	rtw89_warn(rtwdev, "%s: unhandled cnt %u\n", __func__, cnt);
3106 	return RTW89_MR_WMODE_UNKNOWN;
3107 }
3108 
3109 static enum rtw89_mr_ctxtype __rtw89_query_mr_ctxtype(struct rtw89_dev *rtwdev,
3110 						      u8 inst_idx)
3111 {
3112 	struct rtw89_entity_mgnt *mgnt = &rtwdev->hal.entity_mgnt;
3113 	DECLARE_BITMAP(map, NUM_OF_RTW89_CHANCTX) = {};
3114 	unsigned int num[RTW89_BAND_NUM] = {};
3115 	enum rtw89_chanctx_idx chanctx_idx;
3116 	const struct rtw89_chan *chan;
3117 	unsigned int cnt = 0;
3118 	u8 role_idx;
3119 
3120 	if (unlikely(inst_idx >= __RTW89_MLD_MAX_LINK_NUM))
3121 		return RTW89_MR_CTX_UNKNOWN;
3122 
3123 	for (role_idx = 0; role_idx < RTW89_MAX_INTERFACE_NUM; role_idx++) {
3124 		chanctx_idx = mgnt->chanctx_tbl[role_idx][inst_idx];
3125 		if (chanctx_idx == RTW89_CHANCTX_IDLE)
3126 			continue;
3127 
3128 		if (__test_and_set_bit(chanctx_idx, map))
3129 			continue;
3130 
3131 		chan = rtw89_chan_get(rtwdev, chanctx_idx);
3132 		num[chan->band_type]++;
3133 		cnt++;
3134 	}
3135 
3136 	switch (cnt) {
3137 	case 0:
3138 		return RTW89_MR_CTX_NONE;
3139 	case 1:
3140 		if (num[RTW89_BAND_2G])
3141 			return RTW89_MR_CTX1_2GHZ;
3142 		if (num[RTW89_BAND_5G])
3143 			return RTW89_MR_CTX1_5GHZ;
3144 		if (num[RTW89_BAND_6G])
3145 			return RTW89_MR_CTX1_6GHZ;
3146 		break;
3147 	case 2:
3148 		if (num[RTW89_BAND_2G] == 2)
3149 			return RTW89_MR_CTX2_2GHZ;
3150 		if (num[RTW89_BAND_5G] == 2)
3151 			return RTW89_MR_CTX2_5GHZ;
3152 		if (num[RTW89_BAND_6G] == 2)
3153 			return RTW89_MR_CTX2_6GHZ;
3154 		if (num[RTW89_BAND_2G] && num[RTW89_BAND_5G])
3155 			return RTW89_MR_CTX2_2GHZ_5GHZ;
3156 		if (num[RTW89_BAND_2G] && num[RTW89_BAND_6G])
3157 			return RTW89_MR_CTX2_2GHZ_6GHZ;
3158 		if (num[RTW89_BAND_5G] && num[RTW89_BAND_6G])
3159 			return RTW89_MR_CTX2_5GHZ_6GHZ;
3160 		break;
3161 	default:
3162 		break;
3163 	}
3164 
3165 	rtw89_warn(rtwdev, "%s: unhandled cnt %u\n", __func__, cnt);
3166 	return RTW89_MR_CTX_UNKNOWN;
3167 }
3168 
3169 void rtw89_query_mr_chanctx_info(struct rtw89_dev *rtwdev, u8 inst_idx,
3170 				 struct rtw89_mr_chanctx_info *info)
3171 {
3172 	lockdep_assert_wiphy(rtwdev->hw->wiphy);
3173 
3174 	info->wtype = __rtw89_query_mr_wtype(rtwdev);
3175 	info->wmode = __rtw89_query_mr_wmode(rtwdev, inst_idx);
3176 	info->ctxtype = __rtw89_query_mr_ctxtype(rtwdev, inst_idx);
3177 }
3178 
3179 void rtw89_chanctx_track(struct rtw89_dev *rtwdev)
3180 {
3181 	struct rtw89_hal *hal = &rtwdev->hal;
3182 	enum rtw89_entity_mode mode;
3183 
3184 	lockdep_assert_wiphy(rtwdev->hw->wiphy);
3185 
3186 	if (hal->entity_pause)
3187 		return;
3188 
3189 	mode = rtw89_get_entity_mode(rtwdev);
3190 	switch (mode) {
3191 	case RTW89_ENTITY_MODE_MCC:
3192 		rtw89_mcc_track(rtwdev);
3193 		break;
3194 	default:
3195 		break;
3196 	}
3197 }
3198 
3199 void rtw89_chanctx_pause(struct rtw89_dev *rtwdev,
3200 			 const struct rtw89_chanctx_pause_parm *pause_parm)
3201 {
3202 	struct rtw89_hal *hal = &rtwdev->hal;
3203 	enum rtw89_entity_mode mode;
3204 
3205 	lockdep_assert_wiphy(rtwdev->hw->wiphy);
3206 
3207 	if (hal->entity_pause)
3208 		return;
3209 
3210 	rtw89_debug(rtwdev, RTW89_DBG_CHAN, "chanctx pause (rsn: %d)\n", pause_parm->rsn);
3211 
3212 	mode = rtw89_get_entity_mode(rtwdev);
3213 	switch (mode) {
3214 	case RTW89_ENTITY_MODE_MCC:
3215 		rtw89_mcc_stop(rtwdev, pause_parm);
3216 		break;
3217 	default:
3218 		break;
3219 	}
3220 
3221 	hal->entity_pause = true;
3222 }
3223 
3224 static void rtw89_chanctx_proceed_cb(struct rtw89_dev *rtwdev,
3225 				     const struct rtw89_chanctx_cb_parm *parm)
3226 {
3227 	int ret;
3228 
3229 	if (!parm || !parm->cb)
3230 		return;
3231 
3232 	ret = parm->cb(rtwdev, parm->data);
3233 	if (ret)
3234 		rtw89_warn(rtwdev, "%s (%s): cb failed: %d\n", __func__,
3235 			   parm->caller ?: "unknown", ret);
3236 }
3237 
3238 /* pass @cb_parm if there is a @cb_parm->cb which needs to invoke right after
3239  * call rtw89_set_channel() and right before proceed entity according to mode.
3240  */
3241 void rtw89_chanctx_proceed(struct rtw89_dev *rtwdev,
3242 			   const struct rtw89_chanctx_cb_parm *cb_parm)
3243 {
3244 	struct rtw89_hal *hal = &rtwdev->hal;
3245 	enum rtw89_entity_mode mode;
3246 	int ret;
3247 
3248 	lockdep_assert_wiphy(rtwdev->hw->wiphy);
3249 
3250 	if (unlikely(!hal->entity_pause)) {
3251 		rtw89_chanctx_proceed_cb(rtwdev, cb_parm);
3252 		return;
3253 	}
3254 
3255 	rtw89_debug(rtwdev, RTW89_DBG_CHAN, "chanctx proceed\n");
3256 
3257 	hal->entity_pause = false;
3258 	rtw89_set_channel(rtwdev);
3259 
3260 	rtw89_chanctx_proceed_cb(rtwdev, cb_parm);
3261 
3262 	mode = rtw89_get_entity_mode(rtwdev);
3263 	switch (mode) {
3264 	case RTW89_ENTITY_MODE_MCC:
3265 		ret = rtw89_mcc_start(rtwdev);
3266 		if (ret)
3267 			rtw89_warn(rtwdev, "failed to start MCC: %d\n", ret);
3268 		break;
3269 	default:
3270 		break;
3271 	}
3272 
3273 	rtw89_queue_chanctx_work(rtwdev);
3274 }
3275 
3276 static void __rtw89_swap_chanctx(struct rtw89_vif *rtwvif,
3277 				 enum rtw89_chanctx_idx idx1,
3278 				 enum rtw89_chanctx_idx idx2)
3279 {
3280 	struct rtw89_vif_link *rtwvif_link;
3281 	unsigned int link_id;
3282 
3283 	rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) {
3284 		if (!rtwvif_link->chanctx_assigned)
3285 			continue;
3286 
3287 		if (rtwvif_link->chanctx_idx == idx1)
3288 			rtwvif_link->chanctx_idx = idx2;
3289 		else if (rtwvif_link->chanctx_idx == idx2)
3290 			rtwvif_link->chanctx_idx = idx1;
3291 	}
3292 }
3293 
3294 static void rtw89_swap_chanctx(struct rtw89_dev *rtwdev,
3295 			       enum rtw89_chanctx_idx idx1,
3296 			       enum rtw89_chanctx_idx idx2)
3297 {
3298 	struct rtw89_hal *hal = &rtwdev->hal;
3299 	struct rtw89_vif *rtwvif;
3300 	u8 cur;
3301 
3302 	if (idx1 == idx2)
3303 		return;
3304 
3305 	hal->chanctx[idx1].cfg->idx = idx2;
3306 	hal->chanctx[idx2].cfg->idx = idx1;
3307 
3308 	swap(hal->chanctx[idx1], hal->chanctx[idx2]);
3309 
3310 	rtw89_for_each_rtwvif(rtwdev, rtwvif)
3311 		__rtw89_swap_chanctx(rtwvif, idx1, idx2);
3312 
3313 	cur = atomic_read(&hal->roc_chanctx_idx);
3314 	if (cur == idx1)
3315 		atomic_set(&hal->roc_chanctx_idx, idx2);
3316 	else if (cur == idx2)
3317 		atomic_set(&hal->roc_chanctx_idx, idx1);
3318 }
3319 
3320 int rtw89_chanctx_ops_add(struct rtw89_dev *rtwdev,
3321 			  struct ieee80211_chanctx_conf *ctx)
3322 {
3323 	struct rtw89_hal *hal = &rtwdev->hal;
3324 	struct rtw89_chanctx_cfg *cfg = (struct rtw89_chanctx_cfg *)ctx->drv_priv;
3325 	const struct rtw89_chip_info *chip = rtwdev->chip;
3326 	u8 idx;
3327 
3328 	idx = find_first_zero_bit(hal->entity_map, NUM_OF_RTW89_CHANCTX);
3329 	if (idx >= chip->support_chanctx_num)
3330 		return -ENOENT;
3331 
3332 	rtw89_config_entity_chandef(rtwdev, idx, &ctx->def);
3333 	cfg->idx = idx;
3334 	cfg->ref_count = 0;
3335 	hal->chanctx[idx].cfg = cfg;
3336 	return 0;
3337 }
3338 
3339 void rtw89_chanctx_ops_remove(struct rtw89_dev *rtwdev,
3340 			      struct ieee80211_chanctx_conf *ctx)
3341 {
3342 	struct rtw89_chanctx_cfg *cfg = (struct rtw89_chanctx_cfg *)ctx->drv_priv;
3343 
3344 	rtw89_config_entity_chandef(rtwdev, cfg->idx, NULL);
3345 }
3346 
3347 void rtw89_chanctx_ops_change(struct rtw89_dev *rtwdev,
3348 			      struct ieee80211_chanctx_conf *ctx,
3349 			      u32 changed)
3350 {
3351 	struct rtw89_chanctx_cfg *cfg = (struct rtw89_chanctx_cfg *)ctx->drv_priv;
3352 	u8 idx = cfg->idx;
3353 
3354 	if (changed & IEEE80211_CHANCTX_CHANGE_WIDTH) {
3355 		rtw89_config_entity_chandef(rtwdev, idx, &ctx->def);
3356 		rtw89_set_channel(rtwdev);
3357 	}
3358 
3359 	if (changed & IEEE80211_CHANCTX_CHANGE_PUNCTURING)
3360 		rtw89_chan_update_punctured(rtwdev, idx, &ctx->def);
3361 }
3362 
3363 int rtw89_chanctx_ops_assign_vif(struct rtw89_dev *rtwdev,
3364 				 struct rtw89_vif_link *rtwvif_link,
3365 				 struct ieee80211_chanctx_conf *ctx)
3366 {
3367 	struct rtw89_chanctx_cfg *cfg = (struct rtw89_chanctx_cfg *)ctx->drv_priv;
3368 	struct rtw89_vif *rtwvif = rtwvif_link->rtwvif;
3369 	struct rtw89_hal *hal = &rtwdev->hal;
3370 	struct rtw89_entity_mgnt *mgnt = &hal->entity_mgnt;
3371 	struct rtw89_entity_weight w = {};
3372 	int ret;
3373 
3374 	rtwvif_link->chanctx_idx = cfg->idx;
3375 	rtwvif_link->chanctx_assigned = true;
3376 	cfg->ref_count++;
3377 
3378 	if (rtwdev->scanning)
3379 		rtw89_hw_scan_abort(rtwdev, rtwdev->scan_info.scanning_vif);
3380 
3381 	if (list_empty(&rtwvif->mgnt_entry))
3382 		list_add_tail(&rtwvif->mgnt_entry, &mgnt->active_list);
3383 
3384 	if (cfg->idx == RTW89_CHANCTX_0)
3385 		goto out;
3386 
3387 	rtw89_entity_calculate_weight(rtwdev, &w);
3388 	if (w.active_chanctxs != 1)
3389 		goto out;
3390 
3391 	/* put the first active chanctx at RTW89_CHANCTX_0 */
3392 	rtw89_swap_chanctx(rtwdev, cfg->idx, RTW89_CHANCTX_0);
3393 
3394 out:
3395 	ret = rtw89_set_channel(rtwdev);
3396 	if (ret)
3397 		return ret;
3398 
3399 	rtw89_tas_reset(rtwdev, true);
3400 
3401 	return 0;
3402 }
3403 
3404 void rtw89_chanctx_ops_unassign_vif(struct rtw89_dev *rtwdev,
3405 				    struct rtw89_vif_link *rtwvif_link,
3406 				    struct ieee80211_chanctx_conf *ctx)
3407 {
3408 	struct rtw89_chanctx_cfg *cfg = (struct rtw89_chanctx_cfg *)ctx->drv_priv;
3409 	struct rtw89_vif *rtwvif = rtwvif_link->rtwvif;
3410 	struct rtw89_hal *hal = &rtwdev->hal;
3411 	enum rtw89_chanctx_idx roll;
3412 	enum rtw89_entity_mode cur;
3413 	enum rtw89_entity_mode new;
3414 	int ret;
3415 
3416 	rtwvif_link->chanctx_idx = RTW89_CHANCTX_0;
3417 	rtwvif_link->chanctx_assigned = false;
3418 	cfg->ref_count--;
3419 
3420 	if (rtwdev->scanning)
3421 		rtw89_hw_scan_abort(rtwdev, rtwdev->scan_info.scanning_vif);
3422 
3423 	if (!rtw89_vif_is_active_role(rtwvif))
3424 		list_del_init(&rtwvif->mgnt_entry);
3425 
3426 	if (cfg->ref_count != 0)
3427 		goto out;
3428 
3429 	if (cfg->idx != RTW89_CHANCTX_0)
3430 		goto out;
3431 
3432 	roll = find_next_bit(hal->entity_map, NUM_OF_RTW89_CHANCTX,
3433 			     cfg->idx + 1);
3434 	/* Follow rtw89_config_default_chandef() when rtw89_entity_recalc(). */
3435 	if (roll == NUM_OF_RTW89_CHANCTX)
3436 		goto out;
3437 
3438 	/* RTW89_CHANCTX_0 is going to release, and another exists.
3439 	 * Make another roll down to RTW89_CHANCTX_0 to replace.
3440 	 */
3441 	rtw89_swap_chanctx(rtwdev, cfg->idx, roll);
3442 
3443 out:
3444 	if (!hal->entity_pause) {
3445 		cur = rtw89_get_entity_mode(rtwdev);
3446 		switch (cur) {
3447 		case RTW89_ENTITY_MODE_MCC:
3448 			rtw89_mcc_stop(rtwdev, NULL);
3449 			break;
3450 		default:
3451 			break;
3452 		}
3453 	}
3454 
3455 	ret = rtw89_set_channel(rtwdev);
3456 	if (ret)
3457 		return;
3458 
3459 	if (hal->entity_pause)
3460 		return;
3461 
3462 	new = rtw89_get_entity_mode(rtwdev);
3463 	switch (new) {
3464 	case RTW89_ENTITY_MODE_MCC:
3465 		/* re-plan MCC for chanctx changes. */
3466 		ret = rtw89_mcc_start(rtwdev);
3467 		if (ret)
3468 			rtw89_warn(rtwdev, "failed to start MCC: %d\n", ret);
3469 		break;
3470 	default:
3471 		break;
3472 	}
3473 }
3474 
3475 int rtw89_chanctx_ops_reassign_vif(struct rtw89_dev *rtwdev,
3476 				   struct rtw89_vif_link *rtwvif_link,
3477 				   struct ieee80211_chanctx_conf *old_ctx,
3478 				   struct ieee80211_chanctx_conf *new_ctx,
3479 				   bool replace)
3480 {
3481 	int ret;
3482 
3483 	rtw89_chanctx_ops_unassign_vif(rtwdev, rtwvif_link, old_ctx);
3484 
3485 	if (!replace)
3486 		goto assign;
3487 
3488 	rtw89_chanctx_ops_remove(rtwdev, old_ctx);
3489 	ret = rtw89_chanctx_ops_add(rtwdev, new_ctx);
3490 	if (ret) {
3491 		rtw89_err(rtwdev, "%s: failed to add chanctx: %d\n",
3492 			  __func__, ret);
3493 		return ret;
3494 	}
3495 
3496 assign:
3497 	ret = rtw89_chanctx_ops_assign_vif(rtwdev, rtwvif_link, new_ctx);
3498 	if (ret) {
3499 		rtw89_err(rtwdev, "%s: failed to assign chanctx: %d\n",
3500 			  __func__, ret);
3501 		return ret;
3502 	}
3503 
3504 	_rtw89_chan_update_punctured(rtwdev, rtwvif_link, &new_ctx->def);
3505 
3506 	return 0;
3507 }
3508