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