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