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