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