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