1 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
2 /* Copyright(c) 2020-2022 Realtek Corporation
13 static void rtw89_swap_chanctx(struct rtw89_dev *rtwdev,
14 enum rtw89_chanctx_idx idx1,
15 enum rtw89_chanctx_idx idx2);
17 static enum rtw89_subband rtw89_get_subband_type(enum rtw89_band band,
23 switch (center_chan) {
29 switch (center_chan) {
32 return RTW89_CH_5G_BAND_1;
34 return RTW89_CH_5G_BAND_3;
36 return RTW89_CH_5G_BAND_4;
39 switch (center_chan) {
42 return RTW89_CH_6G_BAND_IDX0;
44 return RTW89_CH_6G_BAND_IDX1;
46 return RTW89_CH_6G_BAND_IDX2;
48 return RTW89_CH_6G_BAND_IDX3;
50 return RTW89_CH_6G_BAND_IDX4;
52 return RTW89_CH_6G_BAND_IDX5;
54 return RTW89_CH_6G_BAND_IDX6;
56 return RTW89_CH_6G_BAND_IDX7;
61 static enum rtw89_sc_offset rtw89_get_primary_chan_idx(enum rtw89_bandwidth bw,
70 case RTW89_CHANNEL_WIDTH_20:
71 primary_chan_idx = RTW89_SC_DONT_CARE;
73 case RTW89_CHANNEL_WIDTH_40:
74 if (primary_freq > center_freq)
75 primary_chan_idx = RTW89_SC_20_UPPER;
77 primary_chan_idx = RTW89_SC_20_LOWER;
79 case RTW89_CHANNEL_WIDTH_80:
80 case RTW89_CHANNEL_WIDTH_160:
81 if (primary_freq > center_freq) {
82 offset = (primary_freq - center_freq - 10) / 20;
83 primary_chan_idx = RTW89_SC_20_UPPER + offset * 2;
85 offset = (center_freq - primary_freq - 10) / 20;
86 primary_chan_idx = RTW89_SC_20_LOWER + offset * 2;
91 return primary_chan_idx;
94 static u8 rtw89_get_primary_sb_idx(u8 central_ch, u8 pri_ch,
95 enum rtw89_bandwidth bw)
97 static const u8 prisb_cal_ofst[RTW89_CHANNEL_WIDTH_ORDINARY_NUM] = {
101 if (bw >= RTW89_CHANNEL_WIDTH_ORDINARY_NUM)
104 return (prisb_cal_ofst[bw] + pri_ch - central_ch) / 4;
107 void rtw89_chan_create(struct rtw89_chan *chan, u8 center_chan, u8 primary_chan,
108 enum rtw89_band band, enum rtw89_bandwidth bandwidth)
110 enum nl80211_band nl_band = rtw89_hw_to_nl80211_band(band);
111 u32 center_freq, primary_freq;
113 memset(chan, 0, sizeof(*chan));
114 chan->channel = center_chan;
115 chan->primary_channel = primary_chan;
116 chan->band_type = band;
117 chan->band_width = bandwidth;
119 center_freq = ieee80211_channel_to_frequency(center_chan, nl_band);
120 primary_freq = ieee80211_channel_to_frequency(primary_chan, nl_band);
122 chan->freq = center_freq;
123 chan->subband_type = rtw89_get_subband_type(band, center_chan);
124 chan->pri_ch_idx = rtw89_get_primary_chan_idx(bandwidth, center_freq,
126 chan->pri_sb_idx = rtw89_get_primary_sb_idx(center_chan, primary_chan,
130 bool rtw89_assign_entity_chan(struct rtw89_dev *rtwdev,
131 enum rtw89_chanctx_idx idx,
132 const struct rtw89_chan *new)
134 struct rtw89_hal *hal = &rtwdev->hal;
135 struct rtw89_chan *chan = &hal->chanctx[idx].chan;
136 struct rtw89_chan_rcd *rcd = &hal->chanctx[idx].rcd;
139 rcd->prev_primary_channel = chan->primary_channel;
140 rcd->prev_band_type = chan->band_type;
141 band_changed = new->band_type != chan->band_type;
142 rcd->band_changed = band_changed;
148 int rtw89_iterate_entity_chan(struct rtw89_dev *rtwdev,
149 int (*iterator)(const struct rtw89_chan *chan,
153 struct rtw89_hal *hal = &rtwdev->hal;
154 const struct rtw89_chan *chan;
158 lockdep_assert_held(&rtwdev->mutex);
160 for_each_set_bit(idx, hal->entity_map, NUM_OF_RTW89_CHANCTX) {
161 chan = rtw89_chan_get(rtwdev, idx);
162 ret = iterator(chan, data);
170 static void __rtw89_config_entity_chandef(struct rtw89_dev *rtwdev,
171 enum rtw89_chanctx_idx idx,
172 const struct cfg80211_chan_def *chandef,
175 struct rtw89_hal *hal = &rtwdev->hal;
177 hal->chanctx[idx].chandef = *chandef;
180 set_bit(idx, hal->entity_map);
183 void rtw89_config_entity_chandef(struct rtw89_dev *rtwdev,
184 enum rtw89_chanctx_idx idx,
185 const struct cfg80211_chan_def *chandef)
187 __rtw89_config_entity_chandef(rtwdev, idx, chandef, true);
190 void rtw89_config_roc_chandef(struct rtw89_dev *rtwdev,
191 enum rtw89_chanctx_idx idx,
192 const struct cfg80211_chan_def *chandef)
194 struct rtw89_hal *hal = &rtwdev->hal;
195 enum rtw89_chanctx_idx cur;
198 cur = atomic_cmpxchg(&hal->roc_chanctx_idx,
199 RTW89_CHANCTX_IDLE, idx);
200 if (cur != RTW89_CHANCTX_IDLE) {
201 rtw89_debug(rtwdev, RTW89_DBG_TXRX,
202 "ROC still processing on entity %d\n", idx);
206 hal->roc_chandef = *chandef;
208 cur = atomic_cmpxchg(&hal->roc_chanctx_idx, idx,
213 if (cur == RTW89_CHANCTX_IDLE)
214 rtw89_debug(rtwdev, RTW89_DBG_TXRX,
215 "ROC already finished on entity %d\n", idx);
217 rtw89_debug(rtwdev, RTW89_DBG_TXRX,
218 "ROC is processing on entity %d\n", cur);
222 static void rtw89_config_default_chandef(struct rtw89_dev *rtwdev)
224 struct cfg80211_chan_def chandef = {0};
226 rtw89_get_default_chandef(&chandef);
227 __rtw89_config_entity_chandef(rtwdev, RTW89_CHANCTX_0, &chandef, false);
230 void rtw89_entity_init(struct rtw89_dev *rtwdev)
232 struct rtw89_hal *hal = &rtwdev->hal;
233 struct rtw89_entity_mgnt *mgnt = &hal->entity_mgnt;
235 hal->entity_pause = false;
236 bitmap_zero(hal->entity_map, NUM_OF_RTW89_CHANCTX);
237 bitmap_zero(hal->changes, NUM_OF_RTW89_CHANCTX_CHANGES);
238 atomic_set(&hal->roc_chanctx_idx, RTW89_CHANCTX_IDLE);
240 INIT_LIST_HEAD(&mgnt->active_list);
242 rtw89_config_default_chandef(rtwdev);
245 static bool rtw89_vif_is_active_role(struct rtw89_vif *rtwvif)
247 struct rtw89_vif_link *rtwvif_link;
248 unsigned int link_id;
250 rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id)
251 if (rtwvif_link->chanctx_assigned)
257 static void rtw89_entity_calculate_weight(struct rtw89_dev *rtwdev,
258 struct rtw89_entity_weight *w)
260 struct rtw89_hal *hal = &rtwdev->hal;
261 const struct rtw89_chanctx_cfg *cfg;
262 struct rtw89_vif *rtwvif;
265 for_each_set_bit(idx, hal->entity_map, NUM_OF_RTW89_CHANCTX) {
266 cfg = hal->chanctx[idx].cfg;
268 /* doesn't run with chanctx ops; one channel at most */
269 w->active_chanctxs = 1;
273 if (cfg->ref_count > 0)
274 w->active_chanctxs++;
277 rtw89_for_each_rtwvif(rtwdev, rtwvif) {
278 if (rtw89_vif_is_active_role(rtwvif))
283 static void rtw89_normalize_link_chanctx(struct rtw89_dev *rtwdev,
284 struct rtw89_vif_link *rtwvif_link)
286 struct rtw89_vif *rtwvif = rtwvif_link->rtwvif;
287 struct rtw89_vif_link *cur;
289 if (unlikely(!rtwvif_link->chanctx_assigned))
292 cur = rtw89_vif_get_link_inst(rtwvif, 0);
293 if (!cur || !cur->chanctx_assigned)
296 if (cur == rtwvif_link)
299 rtw89_swap_chanctx(rtwdev, rtwvif_link->chanctx_idx, cur->chanctx_idx);
302 const struct rtw89_chan *__rtw89_mgnt_chan_get(struct rtw89_dev *rtwdev,
303 const char *caller_message,
306 struct rtw89_hal *hal = &rtwdev->hal;
307 struct rtw89_entity_mgnt *mgnt = &hal->entity_mgnt;
308 enum rtw89_chanctx_idx chanctx_idx;
309 enum rtw89_chanctx_idx roc_idx;
310 enum rtw89_entity_mode mode;
313 lockdep_assert_held(&rtwdev->mutex);
315 if (unlikely(link_index >= __RTW89_MLD_MAX_LINK_NUM)) {
316 WARN(1, "link index %u is invalid (max link inst num: %d)\n",
317 link_index, __RTW89_MLD_MAX_LINK_NUM);
321 mode = rtw89_get_entity_mode(rtwdev);
323 case RTW89_ENTITY_MODE_SCC_OR_SMLD:
324 case RTW89_ENTITY_MODE_MCC:
327 case RTW89_ENTITY_MODE_MCC_PREPARE:
331 WARN(1, "Invalid ent mode: %d\n", mode);
335 chanctx_idx = mgnt->chanctx_tbl[role_index][link_index];
336 if (chanctx_idx == RTW89_CHANCTX_IDLE)
339 roc_idx = atomic_read(&hal->roc_chanctx_idx);
340 if (roc_idx != RTW89_CHANCTX_IDLE) {
341 /* ROC is ongoing (given ROC runs on RTW89_ROC_BY_LINK_INDEX).
342 * If @link_index is the same as RTW89_ROC_BY_LINK_INDEX, get
343 * the ongoing ROC chanctx.
345 if (link_index == RTW89_ROC_BY_LINK_INDEX)
346 chanctx_idx = roc_idx;
349 return rtw89_chan_get(rtwdev, chanctx_idx);
352 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
353 "%s (%s): prefetch NULL on link index %u\n",
354 __func__, caller_message ?: "", link_index);
356 return rtw89_chan_get(rtwdev, RTW89_CHANCTX_0);
358 EXPORT_SYMBOL(__rtw89_mgnt_chan_get);
360 static void rtw89_entity_recalc_mgnt_roles(struct rtw89_dev *rtwdev)
362 struct rtw89_hal *hal = &rtwdev->hal;
363 struct rtw89_entity_mgnt *mgnt = &hal->entity_mgnt;
364 struct rtw89_vif_link *link;
365 struct rtw89_vif *role;
369 lockdep_assert_held(&rtwdev->mutex);
371 for (i = 0; i < RTW89_MAX_INTERFACE_NUM; i++)
372 mgnt->active_roles[i] = NULL;
374 for (i = 0; i < RTW89_MAX_INTERFACE_NUM; i++) {
375 for (j = 0; j < __RTW89_MLD_MAX_LINK_NUM; j++)
376 mgnt->chanctx_tbl[i][j] = RTW89_CHANCTX_IDLE;
379 /* To be consistent with legacy behavior, expect the first active role
380 * which uses RTW89_CHANCTX_0 to put at position 0, and make its first
381 * link instance take RTW89_CHANCTX_0. (normalizing)
383 list_for_each_entry(role, &mgnt->active_list, mgnt_entry) {
384 for (i = 0; i < role->links_inst_valid_num; i++) {
385 link = rtw89_vif_get_link_inst(role, i);
386 if (!link || !link->chanctx_assigned)
389 if (link->chanctx_idx == RTW89_CHANCTX_0) {
390 rtw89_normalize_link_chanctx(rtwdev, link);
392 list_del(&role->mgnt_entry);
393 list_add(&role->mgnt_entry, &mgnt->active_list);
399 list_for_each_entry(role, &mgnt->active_list, mgnt_entry) {
400 if (unlikely(pos >= RTW89_MAX_INTERFACE_NUM)) {
402 "%s: active roles are over max iface num\n",
407 for (i = 0; i < role->links_inst_valid_num; i++) {
408 link = rtw89_vif_get_link_inst(role, i);
409 if (!link || !link->chanctx_assigned)
412 mgnt->chanctx_tbl[pos][i] = link->chanctx_idx;
415 mgnt->active_roles[pos++] = role;
419 enum rtw89_entity_mode rtw89_entity_recalc(struct rtw89_dev *rtwdev)
421 DECLARE_BITMAP(recalc_map, NUM_OF_RTW89_CHANCTX) = {};
422 struct rtw89_hal *hal = &rtwdev->hal;
423 const struct cfg80211_chan_def *chandef;
424 struct rtw89_entity_weight w = {};
425 enum rtw89_entity_mode mode;
426 struct rtw89_chan chan;
429 lockdep_assert_held(&rtwdev->mutex);
431 bitmap_copy(recalc_map, hal->entity_map, NUM_OF_RTW89_CHANCTX);
433 rtw89_entity_calculate_weight(rtwdev, &w);
434 switch (w.active_chanctxs) {
436 rtw89_warn(rtwdev, "unknown ent chanctxs weight: %d\n",
438 bitmap_zero(recalc_map, NUM_OF_RTW89_CHANCTX);
441 rtw89_config_default_chandef(rtwdev);
442 set_bit(RTW89_CHANCTX_0, recalc_map);
445 mode = RTW89_ENTITY_MODE_SCC_OR_SMLD;
447 case 2 ... NUM_OF_RTW89_CHANCTX:
448 if (w.active_roles == 1) {
449 mode = RTW89_ENTITY_MODE_SCC_OR_SMLD;
453 if (w.active_roles != NUM_OF_RTW89_MCC_ROLES) {
454 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
455 "unhandled ent: %d chanctxs %d roles\n",
456 w.active_chanctxs, w.active_roles);
457 return RTW89_ENTITY_MODE_UNHANDLED;
460 mode = rtw89_get_entity_mode(rtwdev);
461 if (mode == RTW89_ENTITY_MODE_MCC)
464 mode = RTW89_ENTITY_MODE_MCC_PREPARE;
468 for_each_set_bit(idx, recalc_map, NUM_OF_RTW89_CHANCTX) {
469 chandef = rtw89_chandef_get(rtwdev, idx);
470 rtw89_get_channel_params(chandef, &chan);
471 if (chan.channel == 0) {
472 WARN(1, "Invalid channel on chanctx %d\n", idx);
473 return RTW89_ENTITY_MODE_INVALID;
476 rtw89_assign_entity_chan(rtwdev, idx, &chan);
479 rtw89_entity_recalc_mgnt_roles(rtwdev);
481 if (hal->entity_pause)
482 return rtw89_get_entity_mode(rtwdev);
484 rtw89_set_entity_mode(rtwdev, mode);
488 static void rtw89_chanctx_notify(struct rtw89_dev *rtwdev,
489 enum rtw89_chanctx_state state)
491 const struct rtw89_chip_info *chip = rtwdev->chip;
492 const struct rtw89_chanctx_listener *listener = chip->chanctx_listener;
498 for (i = 0; i < NUM_OF_RTW89_CHANCTX_CALLBACKS; i++) {
499 if (!listener->callbacks[i])
502 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
503 "chanctx notify listener: cb %d, state %d\n",
506 listener->callbacks[i](rtwdev, state);
510 static bool rtw89_concurrent_via_mrc(struct rtw89_dev *rtwdev)
512 enum rtw89_chip_gen chip_gen = rtwdev->chip->chip_gen;
514 return chip_gen == RTW89_CHIP_BE;
517 /* This function centrally manages how MCC roles are sorted and iterated.
518 * And, it guarantees that ordered_idx is less than NUM_OF_RTW89_MCC_ROLES.
519 * So, if data needs to pass an array for ordered_idx, the array can declare
520 * with NUM_OF_RTW89_MCC_ROLES. Besides, the entire iteration will stop
521 * immediately as long as iterator returns a non-zero value.
524 int rtw89_iterate_mcc_roles(struct rtw89_dev *rtwdev,
525 int (*iterator)(struct rtw89_dev *rtwdev,
526 struct rtw89_mcc_role *mcc_role,
527 unsigned int ordered_idx,
531 struct rtw89_mcc_info *mcc = &rtwdev->mcc;
532 struct rtw89_mcc_role * const roles[] = {
539 BUILD_BUG_ON(ARRAY_SIZE(roles) != NUM_OF_RTW89_MCC_ROLES);
541 for (idx = 0; idx < NUM_OF_RTW89_MCC_ROLES; idx++) {
542 ret = iterator(rtwdev, roles[idx], idx, data);
550 static u32 rtw89_mcc_get_tbtt_ofst(struct rtw89_dev *rtwdev,
551 struct rtw89_mcc_role *role, u64 tsf)
553 struct rtw89_vif_link *rtwvif_link = role->rtwvif_link;
554 u32 bcn_intvl_us = ieee80211_tu_to_usec(role->beacon_interval);
555 u64 sync_tsf = READ_ONCE(rtwvif_link->sync_bcn_tsf);
558 if (tsf < sync_tsf) {
559 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
560 "MCC get tbtt ofst: tsf might not update yet\n");
564 div_u64_rem(tsf - sync_tsf, bcn_intvl_us, &remainder);
569 static int __mcc_fw_req_tsf(struct rtw89_dev *rtwdev, u64 *tsf_ref, u64 *tsf_aux)
571 struct rtw89_mcc_info *mcc = &rtwdev->mcc;
572 struct rtw89_mcc_role *ref = &mcc->role_ref;
573 struct rtw89_mcc_role *aux = &mcc->role_aux;
574 struct rtw89_mac_mcc_tsf_rpt rpt = {};
575 struct rtw89_fw_mcc_tsf_req req = {};
578 req.group = mcc->group;
579 req.macid_x = ref->rtwvif_link->mac_id;
580 req.macid_y = aux->rtwvif_link->mac_id;
581 ret = rtw89_fw_h2c_mcc_req_tsf(rtwdev, &req, &rpt);
583 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
584 "MCC h2c failed to request tsf: %d\n", ret);
588 *tsf_ref = (u64)rpt.tsf_x_high << 32 | rpt.tsf_x_low;
589 *tsf_aux = (u64)rpt.tsf_y_high << 32 | rpt.tsf_y_low;
594 static int __mrc_fw_req_tsf(struct rtw89_dev *rtwdev, u64 *tsf_ref, u64 *tsf_aux)
596 struct rtw89_mcc_info *mcc = &rtwdev->mcc;
597 struct rtw89_mcc_role *ref = &mcc->role_ref;
598 struct rtw89_mcc_role *aux = &mcc->role_aux;
599 struct rtw89_fw_mrc_req_tsf_arg arg = {};
600 struct rtw89_mac_mrc_tsf_rpt rpt = {};
603 BUILD_BUG_ON(RTW89_MAC_MRC_MAX_REQ_TSF_NUM < NUM_OF_RTW89_MCC_ROLES);
606 arg.infos[0].band = ref->rtwvif_link->mac_idx;
607 arg.infos[0].port = ref->rtwvif_link->port;
608 arg.infos[1].band = aux->rtwvif_link->mac_idx;
609 arg.infos[1].port = aux->rtwvif_link->port;
611 ret = rtw89_fw_h2c_mrc_req_tsf(rtwdev, &arg, &rpt);
613 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
614 "MRC h2c failed to request tsf: %d\n", ret);
618 *tsf_ref = rpt.tsfs[0];
619 *tsf_aux = rpt.tsfs[1];
624 static u16 rtw89_mcc_get_bcn_ofst(struct rtw89_dev *rtwdev)
626 struct rtw89_mcc_info *mcc = &rtwdev->mcc;
627 struct rtw89_mcc_role *ref = &mcc->role_ref;
628 struct rtw89_mcc_role *aux = &mcc->role_aux;
629 u32 bcn_intvl_ref_us = ieee80211_tu_to_usec(ref->beacon_interval);
630 u32 tbtt_ofst_ref, tbtt_ofst_aux;
631 u64 tsf_ref, tsf_aux;
634 if (rtw89_concurrent_via_mrc(rtwdev))
635 ret = __mrc_fw_req_tsf(rtwdev, &tsf_ref, &tsf_aux);
637 ret = __mcc_fw_req_tsf(rtwdev, &tsf_ref, &tsf_aux);
640 return RTW89_MCC_DFLT_BCN_OFST_TIME;
642 tbtt_ofst_ref = rtw89_mcc_get_tbtt_ofst(rtwdev, ref, tsf_ref);
643 tbtt_ofst_aux = rtw89_mcc_get_tbtt_ofst(rtwdev, aux, tsf_aux);
645 while (tbtt_ofst_ref < tbtt_ofst_aux)
646 tbtt_ofst_ref += bcn_intvl_ref_us;
648 return (tbtt_ofst_ref - tbtt_ofst_aux) / 1024;
652 void rtw89_mcc_role_fw_macid_bitmap_set_bit(struct rtw89_mcc_role *mcc_role,
655 unsigned int idx = bit / 8;
656 unsigned int pos = bit % 8;
658 if (idx >= ARRAY_SIZE(mcc_role->macid_bitmap))
661 mcc_role->macid_bitmap[idx] |= BIT(pos);
665 u32 rtw89_mcc_role_fw_macid_bitmap_to_u32(struct rtw89_mcc_role *mcc_role)
671 for (i = 0; i < ARRAY_SIZE(mcc_role->macid_bitmap); i++) {
672 for (j = 0; j < 8; j++) {
677 if (mcc_role->macid_bitmap[i] & BIT(j))
678 bitmap |= BIT(macid);
686 static void rtw89_mcc_role_macid_sta_iter(void *data, struct ieee80211_sta *sta)
688 struct rtw89_mcc_role *mcc_role = data;
689 struct rtw89_vif *target = mcc_role->rtwvif_link->rtwvif;
690 struct rtw89_sta *rtwsta = sta_to_rtwsta(sta);
691 struct rtw89_vif *rtwvif = rtwsta->rtwvif;
692 struct rtw89_dev *rtwdev = rtwsta->rtwdev;
693 struct rtw89_sta_link *rtwsta_link;
695 if (rtwvif != target)
698 rtwsta_link = rtw89_sta_get_link_inst(rtwsta, 0);
699 if (unlikely(!rtwsta_link)) {
700 rtw89_err(rtwdev, "mcc sta macid: find no link on HW-0\n");
704 rtw89_mcc_role_fw_macid_bitmap_set_bit(mcc_role, rtwsta_link->mac_id);
707 static void rtw89_mcc_fill_role_macid_bitmap(struct rtw89_dev *rtwdev,
708 struct rtw89_mcc_role *mcc_role)
710 struct rtw89_vif_link *rtwvif_link = mcc_role->rtwvif_link;
712 rtw89_mcc_role_fw_macid_bitmap_set_bit(mcc_role, rtwvif_link->mac_id);
713 ieee80211_iterate_stations_atomic(rtwdev->hw,
714 rtw89_mcc_role_macid_sta_iter,
718 static void rtw89_mcc_fill_role_policy(struct rtw89_dev *rtwdev,
719 struct rtw89_mcc_role *mcc_role)
721 struct rtw89_mcc_policy *policy = &mcc_role->policy;
723 policy->c2h_rpt = RTW89_FW_MCC_C2H_RPT_ALL;
724 policy->tx_null_early = RTW89_MCC_DFLT_TX_NULL_EARLY;
725 policy->in_curr_ch = false;
726 policy->dis_sw_retry = true;
727 policy->sw_retry_count = false;
730 policy->dis_tx_null = true;
732 policy->dis_tx_null = false;
735 static void rtw89_mcc_fill_role_limit(struct rtw89_dev *rtwdev,
736 struct rtw89_mcc_role *mcc_role)
738 struct rtw89_vif_link *rtwvif_link = mcc_role->rtwvif_link;
739 struct ieee80211_p2p_noa_desc *noa_desc;
740 struct ieee80211_bss_conf *bss_conf;
741 u32 bcn_intvl_us = ieee80211_tu_to_usec(mcc_role->beacon_interval);
742 u32 max_toa_us, max_tob_us, max_dur_us;
743 u32 start_time, interval, duration;
748 if (!mcc_role->is_go && !mcc_role->is_gc)
753 bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true);
755 /* find the first periodic NoA */
756 for (i = 0; i < RTW89_P2P_MAX_NOA_NUM; i++) {
757 noa_desc = &bss_conf->p2p_noa_attr.desc[i];
758 if (noa_desc->count == 255)
766 start_time = le32_to_cpu(noa_desc->start_time);
767 interval = le32_to_cpu(noa_desc->interval);
768 duration = le32_to_cpu(noa_desc->duration);
772 if (interval != bcn_intvl_us) {
773 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
774 "MCC role limit: mismatch interval: %d vs. %d\n",
775 interval, bcn_intvl_us);
779 ret = rtw89_mac_port_get_tsf(rtwdev, rtwvif_link, &tsf);
781 rtw89_warn(rtwdev, "MCC failed to get port tsf: %d\n", ret);
785 tsf_lmt = (tsf & GENMASK_ULL(63, 32)) | start_time;
786 max_toa_us = rtw89_mcc_get_tbtt_ofst(rtwdev, mcc_role, tsf_lmt);
787 max_dur_us = interval - duration;
788 max_tob_us = max_dur_us - max_toa_us;
790 if (!max_toa_us || !max_tob_us) {
791 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
792 "MCC role limit: hit boundary\n");
796 if (max_dur_us < max_toa_us) {
797 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
798 "MCC role limit: insufficient duration\n");
802 mcc_role->limit.max_toa = max_toa_us / 1024;
803 mcc_role->limit.max_tob = max_tob_us / 1024;
804 mcc_role->limit.max_dur = max_dur_us / 1024;
805 mcc_role->limit.enable = true;
807 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
808 "MCC role limit: max_toa %d, max_tob %d, max_dur %d\n",
809 mcc_role->limit.max_toa, mcc_role->limit.max_tob,
810 mcc_role->limit.max_dur);
813 static int rtw89_mcc_fill_role(struct rtw89_dev *rtwdev,
814 struct rtw89_vif_link *rtwvif_link,
815 struct rtw89_mcc_role *role)
817 struct ieee80211_bss_conf *bss_conf;
818 const struct rtw89_chan *chan;
820 memset(role, 0, sizeof(*role));
821 role->rtwvif_link = rtwvif_link;
825 bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true);
826 role->beacon_interval = bss_conf->beacon_int;
830 if (!role->beacon_interval) {
832 "cannot handle MCC role without beacon interval\n");
836 role->duration = role->beacon_interval / 2;
838 chan = rtw89_chan_get(rtwdev, rtwvif_link->chanctx_idx);
839 role->is_2ghz = chan->band_type == RTW89_BAND_2G;
840 role->is_go = rtwvif_link->wifi_role == RTW89_WIFI_ROLE_P2P_GO;
841 role->is_gc = rtwvif_link->wifi_role == RTW89_WIFI_ROLE_P2P_CLIENT;
843 rtw89_mcc_fill_role_macid_bitmap(rtwdev, role);
844 rtw89_mcc_fill_role_policy(rtwdev, role);
845 rtw89_mcc_fill_role_limit(rtwdev, role);
847 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
848 "MCC role: bcn_intvl %d, is_2ghz %d, is_go %d, is_gc %d\n",
849 role->beacon_interval, role->is_2ghz, role->is_go, role->is_gc);
853 static void rtw89_mcc_fill_bt_role(struct rtw89_dev *rtwdev)
855 struct rtw89_mcc_info *mcc = &rtwdev->mcc;
856 struct rtw89_mcc_bt_role *bt_role = &mcc->bt_role;
858 memset(bt_role, 0, sizeof(*bt_role));
859 bt_role->duration = rtw89_coex_query_bt_req_len(rtwdev, RTW89_PHY_0);
861 rtw89_debug(rtwdev, RTW89_DBG_CHAN, "MCC bt role: dur %d\n",
865 struct rtw89_mcc_fill_role_selector {
866 struct rtw89_vif_link *bind_vif[NUM_OF_RTW89_CHANCTX];
869 static_assert((u8)NUM_OF_RTW89_CHANCTX >= NUM_OF_RTW89_MCC_ROLES);
870 static_assert(RTW89_MAX_INTERFACE_NUM >= NUM_OF_RTW89_MCC_ROLES);
872 static int rtw89_mcc_fill_role_iterator(struct rtw89_dev *rtwdev,
873 struct rtw89_mcc_role *mcc_role,
874 unsigned int ordered_idx,
877 struct rtw89_mcc_fill_role_selector *sel = data;
878 struct rtw89_vif_link *role_vif = sel->bind_vif[ordered_idx];
882 rtw89_warn(rtwdev, "cannot handle MCC without role[%d]\n",
887 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
888 "MCC fill role[%d] with vif <macid %d>\n",
889 ordered_idx, role_vif->mac_id);
891 ret = rtw89_mcc_fill_role(rtwdev, role_vif, mcc_role);
898 static int rtw89_mcc_fill_all_roles(struct rtw89_dev *rtwdev)
900 struct rtw89_hal *hal = &rtwdev->hal;
901 struct rtw89_entity_mgnt *mgnt = &hal->entity_mgnt;
902 struct rtw89_mcc_fill_role_selector sel = {};
903 struct rtw89_vif_link *rtwvif_link;
904 struct rtw89_vif *rtwvif;
908 for (i = 0; i < NUM_OF_RTW89_MCC_ROLES; i++) {
909 rtwvif = mgnt->active_roles[i];
913 rtwvif_link = rtw89_vif_get_link_inst(rtwvif, 0);
914 if (unlikely(!rtwvif_link)) {
915 rtw89_err(rtwdev, "mcc fill roles: find no link on HW-0\n");
919 sel.bind_vif[i] = rtwvif_link;
922 ret = rtw89_iterate_mcc_roles(rtwdev, rtw89_mcc_fill_role_iterator, &sel);
926 rtw89_mcc_fill_bt_role(rtwdev);
930 static void rtw89_mcc_assign_pattern(struct rtw89_dev *rtwdev,
931 const struct rtw89_mcc_pattern *new)
933 struct rtw89_mcc_info *mcc = &rtwdev->mcc;
934 struct rtw89_mcc_role *ref = &mcc->role_ref;
935 struct rtw89_mcc_role *aux = &mcc->role_aux;
936 struct rtw89_mcc_config *config = &mcc->config;
937 struct rtw89_mcc_pattern *pattern = &config->pattern;
939 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
940 "MCC assign pattern: ref {%d | %d}, aux {%d | %d}\n",
941 new->tob_ref, new->toa_ref, new->tob_aux, new->toa_aux);
944 memset(&pattern->courtesy, 0, sizeof(pattern->courtesy));
946 if (pattern->tob_aux <= 0 || pattern->toa_aux <= 0) {
947 pattern->courtesy.macid_tgt = aux->rtwvif_link->mac_id;
948 pattern->courtesy.macid_src = ref->rtwvif_link->mac_id;
949 pattern->courtesy.slot_num = RTW89_MCC_DFLT_COURTESY_SLOT;
950 pattern->courtesy.enable = true;
951 } else if (pattern->tob_ref <= 0 || pattern->toa_ref <= 0) {
952 pattern->courtesy.macid_tgt = ref->rtwvif_link->mac_id;
953 pattern->courtesy.macid_src = aux->rtwvif_link->mac_id;
954 pattern->courtesy.slot_num = RTW89_MCC_DFLT_COURTESY_SLOT;
955 pattern->courtesy.enable = true;
958 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
959 "MCC pattern flags: plan %d, courtesy_en %d\n",
960 pattern->plan, pattern->courtesy.enable);
962 if (!pattern->courtesy.enable)
965 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
966 "MCC pattern courtesy: tgt %d, src %d, slot %d\n",
967 pattern->courtesy.macid_tgt, pattern->courtesy.macid_src,
968 pattern->courtesy.slot_num);
971 /* The follow-up roughly shows the relationship between the parameters
972 * for pattern calculation.
974 * |< duration ref >| (if mid bt) |< duration aux >|
975 * |< tob ref >|< toa ref >| ... |< tob aux >|< toa aux >|
978 * |< beacon offset >|
980 * In loose pattern calculation, we only ensure at least tob_ref and
981 * toa_ref have positive results. If tob_aux or toa_aux is negative
982 * unfortunately, FW will be notified to handle it with courtesy
985 static void __rtw89_mcc_calc_pattern_loose(struct rtw89_dev *rtwdev,
986 struct rtw89_mcc_pattern *ptrn,
989 struct rtw89_mcc_info *mcc = &rtwdev->mcc;
990 struct rtw89_mcc_role *ref = &mcc->role_ref;
991 struct rtw89_mcc_role *aux = &mcc->role_aux;
992 struct rtw89_mcc_config *config = &mcc->config;
993 u16 bcn_ofst = config->beacon_offset;
994 u16 bt_dur_in_mid = 0;
999 *ptrn = (typeof(*ptrn)){
1000 .plan = hdl_bt ? RTW89_MCC_PLAN_TAIL_BT : RTW89_MCC_PLAN_NO_BT,
1006 max_bcn_ofst = ref->duration + aux->duration;
1007 if (ref->limit.enable)
1008 max_bcn_ofst = min_t(u16, max_bcn_ofst,
1009 ref->limit.max_toa + aux->duration);
1010 else if (aux->limit.enable)
1011 max_bcn_ofst = min_t(u16, max_bcn_ofst,
1012 ref->duration + aux->limit.max_tob);
1014 if (bcn_ofst > max_bcn_ofst && bcn_ofst >= mcc->bt_role.duration) {
1015 bt_dur_in_mid = mcc->bt_role.duration;
1016 ptrn->plan = RTW89_MCC_PLAN_MID_BT;
1020 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1021 "MCC calc ptrn_ls: plan %d, bcn_ofst %d\n",
1022 ptrn->plan, bcn_ofst);
1024 res = bcn_ofst - bt_dur_in_mid;
1025 upper = min_t(s16, ref->duration, res);
1028 if (ref->limit.enable) {
1029 upper = min_t(s16, upper, ref->limit.max_toa);
1030 lower = max_t(s16, lower, ref->duration - ref->limit.max_tob);
1031 } else if (aux->limit.enable) {
1032 upper = min_t(s16, upper,
1033 res - (aux->duration - aux->limit.max_toa));
1034 lower = max_t(s16, lower, res - aux->limit.max_tob);
1038 ptrn->toa_ref = (upper + lower) / 2;
1040 ptrn->toa_ref = lower;
1042 ptrn->tob_ref = ref->duration - ptrn->toa_ref;
1043 ptrn->tob_aux = res - ptrn->toa_ref;
1044 ptrn->toa_aux = aux->duration - ptrn->tob_aux;
1047 /* In strict pattern calculation, we consider timing that might need
1048 * for HW stuffs, i.e. min_tob and min_toa.
1050 static int __rtw89_mcc_calc_pattern_strict(struct rtw89_dev *rtwdev,
1051 struct rtw89_mcc_pattern *ptrn)
1053 struct rtw89_mcc_info *mcc = &rtwdev->mcc;
1054 struct rtw89_mcc_role *ref = &mcc->role_ref;
1055 struct rtw89_mcc_role *aux = &mcc->role_aux;
1056 struct rtw89_mcc_config *config = &mcc->config;
1057 u16 min_tob = RTW89_MCC_EARLY_RX_BCN_TIME;
1058 u16 min_toa = RTW89_MCC_MIN_RX_BCN_TIME;
1059 u16 bcn_ofst = config->beacon_offset;
1060 s16 upper_toa_ref, lower_toa_ref;
1061 s16 upper_tob_aux, lower_tob_aux;
1065 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1066 "MCC calc ptrn_st: plan %d, bcn_ofst %d\n",
1067 ptrn->plan, bcn_ofst);
1069 if (ptrn->plan == RTW89_MCC_PLAN_MID_BT)
1070 bt_dur_in_mid = mcc->bt_role.duration;
1074 if (ref->duration < min_tob + min_toa) {
1075 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1076 "MCC calc ptrn_st: not meet ref dur cond\n");
1080 if (aux->duration < min_tob + min_toa) {
1081 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1082 "MCC calc ptrn_st: not meet aux dur cond\n");
1086 res = bcn_ofst - min_toa - min_tob - bt_dur_in_mid;
1088 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1089 "MCC calc ptrn_st: not meet bcn_ofst cond\n");
1093 upper_toa_ref = min_t(s16, min_toa + res, ref->duration - min_tob);
1094 lower_toa_ref = min_toa;
1095 upper_tob_aux = min_t(s16, min_tob + res, aux->duration - min_toa);
1096 lower_tob_aux = min_tob;
1098 if (ref->limit.enable) {
1099 if (min_tob > ref->limit.max_tob || min_toa > ref->limit.max_toa) {
1100 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1101 "MCC calc ptrn_st: conflict ref limit\n");
1105 upper_toa_ref = min_t(s16, upper_toa_ref, ref->limit.max_toa);
1106 lower_toa_ref = max_t(s16, lower_toa_ref,
1107 ref->duration - ref->limit.max_tob);
1108 } else if (aux->limit.enable) {
1109 if (min_tob > aux->limit.max_tob || min_toa > aux->limit.max_toa) {
1110 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1111 "MCC calc ptrn_st: conflict aux limit\n");
1115 upper_tob_aux = min_t(s16, upper_tob_aux, aux->limit.max_tob);
1116 lower_tob_aux = max_t(s16, lower_tob_aux,
1117 aux->duration - aux->limit.max_toa);
1120 upper_toa_ref = min_t(s16, upper_toa_ref,
1121 bcn_ofst - bt_dur_in_mid - lower_tob_aux);
1122 lower_toa_ref = max_t(s16, lower_toa_ref,
1123 bcn_ofst - bt_dur_in_mid - upper_tob_aux);
1124 if (lower_toa_ref > upper_toa_ref) {
1125 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1126 "MCC calc ptrn_st: conflict boundary\n");
1130 ptrn->toa_ref = (upper_toa_ref + lower_toa_ref) / 2;
1131 ptrn->tob_ref = ref->duration - ptrn->toa_ref;
1132 ptrn->tob_aux = bcn_ofst - ptrn->toa_ref - bt_dur_in_mid;
1133 ptrn->toa_aux = aux->duration - ptrn->tob_aux;
1137 static int rtw89_mcc_calc_pattern(struct rtw89_dev *rtwdev, bool hdl_bt)
1139 struct rtw89_mcc_info *mcc = &rtwdev->mcc;
1140 struct rtw89_mcc_role *ref = &mcc->role_ref;
1141 struct rtw89_mcc_role *aux = &mcc->role_aux;
1142 bool sel_plan[NUM_OF_RTW89_MCC_PLAN] = {};
1143 struct rtw89_mcc_pattern ptrn;
1147 if (ref->limit.enable && aux->limit.enable) {
1148 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1149 "MCC calc ptrn: not support dual limited roles\n");
1153 if (ref->limit.enable &&
1154 ref->duration > ref->limit.max_tob + ref->limit.max_toa) {
1155 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1156 "MCC calc ptrn: not fit ref limit\n");
1160 if (aux->limit.enable &&
1161 aux->duration > aux->limit.max_tob + aux->limit.max_toa) {
1162 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1163 "MCC calc ptrn: not fit aux limit\n");
1168 sel_plan[RTW89_MCC_PLAN_TAIL_BT] = true;
1169 sel_plan[RTW89_MCC_PLAN_MID_BT] = true;
1171 sel_plan[RTW89_MCC_PLAN_NO_BT] = true;
1174 for (i = 0; i < NUM_OF_RTW89_MCC_PLAN; i++) {
1178 ptrn = (typeof(ptrn)){
1182 ret = __rtw89_mcc_calc_pattern_strict(rtwdev, &ptrn);
1184 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1185 "MCC calc ptrn_st with plan %d: fail\n", i);
1190 __rtw89_mcc_calc_pattern_loose(rtwdev, &ptrn, hdl_bt);
1193 rtw89_mcc_assign_pattern(rtwdev, &ptrn);
1197 static void rtw89_mcc_set_default_pattern(struct rtw89_dev *rtwdev)
1199 struct rtw89_mcc_info *mcc = &rtwdev->mcc;
1200 struct rtw89_mcc_role *ref = &mcc->role_ref;
1201 struct rtw89_mcc_role *aux = &mcc->role_aux;
1202 struct rtw89_mcc_pattern tmp = {};
1204 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1205 "MCC use default pattern unexpectedly\n");
1207 tmp.plan = RTW89_MCC_PLAN_NO_BT;
1208 tmp.tob_ref = ref->duration / 2;
1209 tmp.toa_ref = ref->duration - tmp.tob_ref;
1210 tmp.tob_aux = aux->duration / 2;
1211 tmp.toa_aux = aux->duration - tmp.tob_aux;
1213 rtw89_mcc_assign_pattern(rtwdev, &tmp);
1216 static void rtw89_mcc_set_duration_go_sta(struct rtw89_dev *rtwdev,
1217 struct rtw89_mcc_role *role_go,
1218 struct rtw89_mcc_role *role_sta)
1220 struct rtw89_mcc_info *mcc = &rtwdev->mcc;
1221 struct rtw89_mcc_config *config = &mcc->config;
1222 u16 mcc_intvl = config->mcc_interval;
1223 u16 dur_go, dur_sta;
1225 dur_go = clamp_t(u16, role_go->duration, RTW89_MCC_MIN_GO_DURATION,
1226 mcc_intvl - RTW89_MCC_MIN_STA_DURATION);
1227 if (role_go->limit.enable)
1228 dur_go = min(dur_go, role_go->limit.max_dur);
1229 dur_sta = mcc_intvl - dur_go;
1231 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1232 "MCC set dur: (go, sta) {%d, %d} -> {%d, %d}\n",
1233 role_go->duration, role_sta->duration, dur_go, dur_sta);
1235 role_go->duration = dur_go;
1236 role_sta->duration = dur_sta;
1239 static void rtw89_mcc_set_duration_gc_sta(struct rtw89_dev *rtwdev)
1241 struct rtw89_mcc_info *mcc = &rtwdev->mcc;
1242 struct rtw89_mcc_role *ref = &mcc->role_ref;
1243 struct rtw89_mcc_role *aux = &mcc->role_aux;
1244 struct rtw89_mcc_config *config = &mcc->config;
1245 u16 mcc_intvl = config->mcc_interval;
1246 u16 dur_ref, dur_aux;
1248 if (ref->duration < RTW89_MCC_MIN_STA_DURATION) {
1249 dur_ref = RTW89_MCC_MIN_STA_DURATION;
1250 dur_aux = mcc_intvl - dur_ref;
1251 } else if (aux->duration < RTW89_MCC_MIN_STA_DURATION) {
1252 dur_aux = RTW89_MCC_MIN_STA_DURATION;
1253 dur_ref = mcc_intvl - dur_aux;
1255 dur_ref = ref->duration;
1256 dur_aux = mcc_intvl - dur_ref;
1259 if (ref->limit.enable) {
1260 dur_ref = min(dur_ref, ref->limit.max_dur);
1261 dur_aux = mcc_intvl - dur_ref;
1262 } else if (aux->limit.enable) {
1263 dur_aux = min(dur_aux, aux->limit.max_dur);
1264 dur_ref = mcc_intvl - dur_aux;
1267 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1268 "MCC set dur: (ref, aux) {%d ~ %d} -> {%d ~ %d}\n",
1269 ref->duration, aux->duration, dur_ref, dur_aux);
1271 ref->duration = dur_ref;
1272 aux->duration = dur_aux;
1275 struct rtw89_mcc_mod_dur_data {
1280 } parm[NUM_OF_RTW89_MCC_ROLES];
1283 static int rtw89_mcc_mod_dur_get_iterator(struct rtw89_dev *rtwdev,
1284 struct rtw89_mcc_role *mcc_role,
1285 unsigned int ordered_idx,
1288 struct rtw89_mcc_mod_dur_data *p = data;
1291 p->parm[ordered_idx].dur = mcc_role->duration;
1293 if (mcc_role->is_go)
1294 min = RTW89_MCC_MIN_GO_DURATION;
1296 min = RTW89_MCC_MIN_STA_DURATION;
1298 p->parm[ordered_idx].room = max_t(s32, p->parm[ordered_idx].dur - min, 0);
1300 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1301 "MCC mod dur: chk role[%u]: dur %u, min %u, room %u\n",
1302 ordered_idx, p->parm[ordered_idx].dur, min,
1303 p->parm[ordered_idx].room);
1305 p->available += p->parm[ordered_idx].room;
1309 static int rtw89_mcc_mod_dur_put_iterator(struct rtw89_dev *rtwdev,
1310 struct rtw89_mcc_role *mcc_role,
1311 unsigned int ordered_idx,
1314 struct rtw89_mcc_mod_dur_data *p = data;
1316 mcc_role->duration = p->parm[ordered_idx].dur;
1318 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1319 "MCC mod dur: set role[%u]: dur %u\n",
1320 ordered_idx, p->parm[ordered_idx].dur);
1324 static void rtw89_mcc_mod_duration_dual_2ghz_with_bt(struct rtw89_dev *rtwdev)
1326 struct rtw89_mcc_info *mcc = &rtwdev->mcc;
1327 struct rtw89_mcc_config *config = &mcc->config;
1328 struct rtw89_mcc_mod_dur_data data = {};
1329 u16 mcc_intvl = config->mcc_interval;
1330 u16 bt_dur = mcc->bt_role.duration;
1333 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1334 "MCC mod dur (dual 2ghz): mcc_intvl %u, raw bt_dur %u\n",
1337 rtw89_iterate_mcc_roles(rtwdev, rtw89_mcc_mod_dur_get_iterator, &data);
1339 bt_dur = clamp_t(u16, bt_dur, 1, data.available / 3);
1340 wifi_dur = mcc_intvl - bt_dur;
1342 if (data.parm[0].room <= data.parm[1].room) {
1343 data.parm[0].dur -= min_t(u16, bt_dur / 2, data.parm[0].room);
1344 data.parm[1].dur = wifi_dur - data.parm[0].dur;
1346 data.parm[1].dur -= min_t(u16, bt_dur / 2, data.parm[1].room);
1347 data.parm[0].dur = wifi_dur - data.parm[1].dur;
1350 rtw89_iterate_mcc_roles(rtwdev, rtw89_mcc_mod_dur_put_iterator, &data);
1352 rtw89_debug(rtwdev, RTW89_DBG_CHAN, "MCC mod dur: set bt: dur %u\n", bt_dur);
1353 mcc->bt_role.duration = bt_dur;
1357 void rtw89_mcc_mod_duration_diff_band_with_bt(struct rtw89_dev *rtwdev,
1358 struct rtw89_mcc_role *role_2ghz,
1359 struct rtw89_mcc_role *role_non_2ghz)
1361 struct rtw89_mcc_info *mcc = &rtwdev->mcc;
1362 struct rtw89_mcc_config *config = &mcc->config;
1363 u16 dur_2ghz, dur_non_2ghz;
1364 u16 bt_dur, mcc_intvl;
1366 dur_2ghz = role_2ghz->duration;
1367 dur_non_2ghz = role_non_2ghz->duration;
1368 mcc_intvl = config->mcc_interval;
1369 bt_dur = mcc->bt_role.duration;
1371 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1372 "MCC mod dur (diff band): mcc_intvl %u, bt_dur %u\n",
1375 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1376 "MCC mod dur: check dur_2ghz %u, dur_non_2ghz %u\n",
1377 dur_2ghz, dur_non_2ghz);
1379 if (dur_non_2ghz >= bt_dur) {
1380 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1381 "MCC mod dur: dur_non_2ghz is enough for bt\n");
1385 dur_non_2ghz = bt_dur;
1386 dur_2ghz = mcc_intvl - dur_non_2ghz;
1388 if (role_non_2ghz->limit.enable) {
1389 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1390 "MCC mod dur: dur_non_2ghz is limited with max %u\n",
1391 role_non_2ghz->limit.max_dur);
1393 dur_non_2ghz = min(dur_non_2ghz, role_non_2ghz->limit.max_dur);
1394 dur_2ghz = mcc_intvl - dur_non_2ghz;
1397 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1398 "MCC mod dur: set dur_2ghz %u, dur_non_2ghz %u\n",
1399 dur_2ghz, dur_non_2ghz);
1401 role_2ghz->duration = dur_2ghz;
1402 role_non_2ghz->duration = dur_non_2ghz;
1405 static bool rtw89_mcc_duration_decision_on_bt(struct rtw89_dev *rtwdev)
1407 struct rtw89_mcc_info *mcc = &rtwdev->mcc;
1408 struct rtw89_mcc_role *ref = &mcc->role_ref;
1409 struct rtw89_mcc_role *aux = &mcc->role_aux;
1410 struct rtw89_mcc_bt_role *bt_role = &mcc->bt_role;
1412 if (!bt_role->duration)
1415 if (ref->is_2ghz && aux->is_2ghz) {
1416 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1417 "MCC dual roles are on 2GHz; consider BT duration\n");
1419 rtw89_mcc_mod_duration_dual_2ghz_with_bt(rtwdev);
1423 if (!ref->is_2ghz && !aux->is_2ghz) {
1424 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1425 "MCC dual roles are not on 2GHz; ignore BT duration\n");
1429 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1430 "MCC one role is on 2GHz; modify another for BT duration\n");
1433 rtw89_mcc_mod_duration_diff_band_with_bt(rtwdev, ref, aux);
1435 rtw89_mcc_mod_duration_diff_band_with_bt(rtwdev, aux, ref);
1440 static void rtw89_mcc_sync_tbtt(struct rtw89_dev *rtwdev,
1441 struct rtw89_mcc_role *tgt,
1442 struct rtw89_mcc_role *src,
1445 struct rtw89_mcc_info *mcc = &rtwdev->mcc;
1446 struct rtw89_mcc_config *config = &mcc->config;
1447 u16 beacon_offset_us = ieee80211_tu_to_usec(config->beacon_offset);
1448 u32 bcn_intvl_src_us = ieee80211_tu_to_usec(src->beacon_interval);
1449 u32 cur_tbtt_ofst_src;
1456 ret = rtw89_mac_port_get_tsf(rtwdev, src->rtwvif_link, &tsf_src);
1458 rtw89_warn(rtwdev, "MCC failed to get port tsf: %d\n", ret);
1462 cur_tbtt_ofst_src = rtw89_mcc_get_tbtt_ofst(rtwdev, src, tsf_src);
1465 tbtt_tgt = tsf_src - cur_tbtt_ofst_src + beacon_offset_us;
1467 tbtt_tgt = tsf_src - cur_tbtt_ofst_src +
1468 (bcn_intvl_src_us - beacon_offset_us);
1470 div_u64_rem(tbtt_tgt, bcn_intvl_src_us, &remainder);
1471 tsf_ofst_tgt = bcn_intvl_src_us - remainder;
1473 config->sync.macid_tgt = tgt->rtwvif_link->mac_id;
1474 config->sync.band_tgt = tgt->rtwvif_link->mac_idx;
1475 config->sync.port_tgt = tgt->rtwvif_link->port;
1476 config->sync.macid_src = src->rtwvif_link->mac_id;
1477 config->sync.band_src = src->rtwvif_link->mac_idx;
1478 config->sync.port_src = src->rtwvif_link->port;
1479 config->sync.offset = tsf_ofst_tgt / 1024;
1480 config->sync.enable = true;
1482 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1483 "MCC sync tbtt: tgt %d, src %d, offset %d\n",
1484 config->sync.macid_tgt, config->sync.macid_src,
1485 config->sync.offset);
1487 rtw89_mac_port_tsf_sync(rtwdev, tgt->rtwvif_link, src->rtwvif_link,
1488 config->sync.offset);
1491 static int rtw89_mcc_fill_start_tsf(struct rtw89_dev *rtwdev)
1493 struct rtw89_mcc_info *mcc = &rtwdev->mcc;
1494 struct rtw89_mcc_role *ref = &mcc->role_ref;
1495 struct rtw89_mcc_config *config = &mcc->config;
1496 u32 bcn_intvl_ref_us = ieee80211_tu_to_usec(ref->beacon_interval);
1497 u32 tob_ref_us = ieee80211_tu_to_usec(config->pattern.tob_ref);
1498 struct rtw89_vif_link *rtwvif_link = ref->rtwvif_link;
1504 ret = rtw89_mac_port_get_tsf(rtwdev, rtwvif_link, &tsf);
1506 rtw89_warn(rtwdev, "MCC failed to get port tsf: %d\n", ret);
1512 min_time += ieee80211_tu_to_usec(RTW89_MCC_SHORT_TRIGGER_TIME);
1514 min_time += ieee80211_tu_to_usec(RTW89_MCC_LONG_TRIGGER_TIME);
1516 cur_tbtt_ofst = rtw89_mcc_get_tbtt_ofst(rtwdev, ref, tsf);
1517 start_tsf = tsf - cur_tbtt_ofst + bcn_intvl_ref_us - tob_ref_us;
1518 while (start_tsf < min_time)
1519 start_tsf += bcn_intvl_ref_us;
1521 config->start_tsf = start_tsf;
1525 static int rtw89_mcc_fill_config(struct rtw89_dev *rtwdev)
1527 struct rtw89_mcc_info *mcc = &rtwdev->mcc;
1528 struct rtw89_mcc_role *ref = &mcc->role_ref;
1529 struct rtw89_mcc_role *aux = &mcc->role_aux;
1530 struct rtw89_mcc_config *config = &mcc->config;
1534 memset(config, 0, sizeof(*config));
1536 switch (mcc->mode) {
1537 case RTW89_MCC_MODE_GO_STA:
1538 config->beacon_offset = RTW89_MCC_DFLT_BCN_OFST_TIME;
1540 rtw89_mcc_sync_tbtt(rtwdev, ref, aux, false);
1541 config->mcc_interval = ref->beacon_interval;
1542 rtw89_mcc_set_duration_go_sta(rtwdev, ref, aux);
1544 rtw89_mcc_sync_tbtt(rtwdev, aux, ref, true);
1545 config->mcc_interval = aux->beacon_interval;
1546 rtw89_mcc_set_duration_go_sta(rtwdev, aux, ref);
1549 case RTW89_MCC_MODE_GC_STA:
1550 config->beacon_offset = rtw89_mcc_get_bcn_ofst(rtwdev);
1551 config->mcc_interval = ref->beacon_interval;
1552 rtw89_mcc_set_duration_gc_sta(rtwdev);
1555 rtw89_warn(rtwdev, "MCC unknown mode: %d\n", mcc->mode);
1559 hdl_bt = rtw89_mcc_duration_decision_on_bt(rtwdev);
1560 rtw89_debug(rtwdev, RTW89_DBG_CHAN, "MCC handle bt: %d\n", hdl_bt);
1562 ret = rtw89_mcc_calc_pattern(rtwdev, hdl_bt);
1566 rtw89_mcc_set_default_pattern(rtwdev);
1569 return rtw89_mcc_fill_start_tsf(rtwdev);
1572 static int __mcc_fw_add_role(struct rtw89_dev *rtwdev, struct rtw89_mcc_role *role)
1574 struct rtw89_mcc_info *mcc = &rtwdev->mcc;
1575 struct rtw89_mcc_config *config = &mcc->config;
1576 struct rtw89_mcc_pattern *pattern = &config->pattern;
1577 struct rtw89_mcc_courtesy *courtesy = &pattern->courtesy;
1578 struct rtw89_mcc_policy *policy = &role->policy;
1579 struct rtw89_fw_mcc_add_req req = {};
1580 const struct rtw89_chan *chan;
1583 chan = rtw89_chan_get(rtwdev, role->rtwvif_link->chanctx_idx);
1584 req.central_ch_seg0 = chan->channel;
1585 req.primary_ch = chan->primary_channel;
1586 req.bandwidth = chan->band_width;
1587 req.ch_band_type = chan->band_type;
1589 req.macid = role->rtwvif_link->mac_id;
1590 req.group = mcc->group;
1591 req.c2h_rpt = policy->c2h_rpt;
1592 req.tx_null_early = policy->tx_null_early;
1593 req.dis_tx_null = policy->dis_tx_null;
1594 req.in_curr_ch = policy->in_curr_ch;
1595 req.sw_retry_count = policy->sw_retry_count;
1596 req.dis_sw_retry = policy->dis_sw_retry;
1597 req.duration = role->duration;
1598 req.btc_in_2g = false;
1600 if (courtesy->enable && courtesy->macid_src == req.macid) {
1601 req.courtesy_target = courtesy->macid_tgt;
1602 req.courtesy_num = courtesy->slot_num;
1603 req.courtesy_en = true;
1606 ret = rtw89_fw_h2c_add_mcc(rtwdev, &req);
1608 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1609 "MCC h2c failed to add wifi role: %d\n", ret);
1613 ret = rtw89_fw_h2c_mcc_macid_bitmap(rtwdev, mcc->group,
1614 role->rtwvif_link->mac_id,
1615 role->macid_bitmap);
1617 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1618 "MCC h2c failed to set macid bitmap: %d\n", ret);
1626 void __mrc_fw_add_role(struct rtw89_dev *rtwdev, struct rtw89_mcc_role *role,
1627 struct rtw89_fw_mrc_add_arg *arg, u8 slot_idx)
1629 struct rtw89_mcc_info *mcc = &rtwdev->mcc;
1630 struct rtw89_mcc_role *ref = &mcc->role_ref;
1631 struct rtw89_mcc_policy *policy = &role->policy;
1632 struct rtw89_fw_mrc_add_slot_arg *slot_arg;
1633 const struct rtw89_chan *chan;
1635 slot_arg = &arg->slots[slot_idx];
1636 role->slot_idx = slot_idx;
1638 slot_arg->duration = role->duration;
1639 slot_arg->role_num = 1;
1641 chan = rtw89_chan_get(rtwdev, role->rtwvif_link->chanctx_idx);
1643 slot_arg->roles[0].role_type = RTW89_H2C_MRC_ROLE_WIFI;
1644 slot_arg->roles[0].is_master = role == ref;
1645 slot_arg->roles[0].band = chan->band_type;
1646 slot_arg->roles[0].bw = chan->band_width;
1647 slot_arg->roles[0].central_ch = chan->channel;
1648 slot_arg->roles[0].primary_ch = chan->primary_channel;
1649 slot_arg->roles[0].en_tx_null = !policy->dis_tx_null;
1650 slot_arg->roles[0].null_early = policy->tx_null_early;
1651 slot_arg->roles[0].macid = role->rtwvif_link->mac_id;
1652 slot_arg->roles[0].macid_main_bitmap =
1653 rtw89_mcc_role_fw_macid_bitmap_to_u32(role);
1656 static int __mcc_fw_add_bt_role(struct rtw89_dev *rtwdev)
1658 struct rtw89_mcc_info *mcc = &rtwdev->mcc;
1659 struct rtw89_mcc_bt_role *bt_role = &mcc->bt_role;
1660 struct rtw89_fw_mcc_add_req req = {};
1663 req.group = mcc->group;
1664 req.duration = bt_role->duration;
1665 req.btc_in_2g = true;
1667 ret = rtw89_fw_h2c_add_mcc(rtwdev, &req);
1669 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1670 "MCC h2c failed to add bt role: %d\n", ret);
1678 void __mrc_fw_add_bt_role(struct rtw89_dev *rtwdev,
1679 struct rtw89_fw_mrc_add_arg *arg, u8 slot_idx)
1681 struct rtw89_mcc_info *mcc = &rtwdev->mcc;
1682 struct rtw89_mcc_bt_role *bt_role = &mcc->bt_role;
1683 struct rtw89_fw_mrc_add_slot_arg *slot_arg = &arg->slots[slot_idx];
1685 slot_arg->duration = bt_role->duration;
1686 slot_arg->role_num = 1;
1688 slot_arg->roles[0].role_type = RTW89_H2C_MRC_ROLE_BT;
1691 static int __mcc_fw_start(struct rtw89_dev *rtwdev, bool replace)
1693 struct rtw89_mcc_info *mcc = &rtwdev->mcc;
1694 struct rtw89_mcc_role *ref = &mcc->role_ref;
1695 struct rtw89_mcc_role *aux = &mcc->role_aux;
1696 struct rtw89_mcc_config *config = &mcc->config;
1697 struct rtw89_mcc_pattern *pattern = &config->pattern;
1698 struct rtw89_mcc_sync *sync = &config->sync;
1699 struct rtw89_fw_mcc_start_req req = {};
1703 req.old_group = mcc->group;
1704 req.old_group_action = RTW89_FW_MCC_OLD_GROUP_ACT_REPLACE;
1705 mcc->group = RTW89_MCC_NEXT_GROUP(mcc->group);
1708 req.group = mcc->group;
1710 switch (pattern->plan) {
1711 case RTW89_MCC_PLAN_TAIL_BT:
1712 ret = __mcc_fw_add_role(rtwdev, ref);
1715 ret = __mcc_fw_add_role(rtwdev, aux);
1718 ret = __mcc_fw_add_bt_role(rtwdev);
1722 req.btc_in_group = true;
1724 case RTW89_MCC_PLAN_MID_BT:
1725 ret = __mcc_fw_add_role(rtwdev, ref);
1728 ret = __mcc_fw_add_bt_role(rtwdev);
1731 ret = __mcc_fw_add_role(rtwdev, aux);
1735 req.btc_in_group = true;
1737 case RTW89_MCC_PLAN_NO_BT:
1738 ret = __mcc_fw_add_role(rtwdev, ref);
1741 ret = __mcc_fw_add_role(rtwdev, aux);
1745 req.btc_in_group = false;
1748 rtw89_warn(rtwdev, "MCC unknown plan: %d\n", pattern->plan);
1753 ret = rtw89_fw_h2c_mcc_sync(rtwdev, req.group, sync->macid_src,
1754 sync->macid_tgt, sync->offset);
1756 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1757 "MCC h2c failed to trigger sync: %d\n", ret);
1762 req.macid = ref->rtwvif_link->mac_id;
1763 req.tsf_high = config->start_tsf >> 32;
1764 req.tsf_low = config->start_tsf;
1766 ret = rtw89_fw_h2c_start_mcc(rtwdev, &req);
1768 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1769 "MCC h2c failed to trigger start: %d\n", ret);
1776 static void __mrc_fw_add_courtesy(struct rtw89_dev *rtwdev,
1777 struct rtw89_fw_mrc_add_arg *arg)
1779 struct rtw89_mcc_info *mcc = &rtwdev->mcc;
1780 struct rtw89_mcc_role *ref = &mcc->role_ref;
1781 struct rtw89_mcc_role *aux = &mcc->role_aux;
1782 struct rtw89_mcc_config *config = &mcc->config;
1783 struct rtw89_mcc_pattern *pattern = &config->pattern;
1784 struct rtw89_mcc_courtesy *courtesy = &pattern->courtesy;
1785 struct rtw89_fw_mrc_add_slot_arg *slot_arg_src;
1788 if (!courtesy->enable)
1791 if (courtesy->macid_src == ref->rtwvif_link->mac_id) {
1792 slot_arg_src = &arg->slots[ref->slot_idx];
1793 slot_idx_tgt = aux->slot_idx;
1795 slot_arg_src = &arg->slots[aux->slot_idx];
1796 slot_idx_tgt = ref->slot_idx;
1799 slot_arg_src->courtesy_target = slot_idx_tgt;
1800 slot_arg_src->courtesy_period = courtesy->slot_num;
1801 slot_arg_src->courtesy_en = true;
1804 static int __mrc_fw_start(struct rtw89_dev *rtwdev, bool replace)
1806 struct rtw89_mcc_info *mcc = &rtwdev->mcc;
1807 struct rtw89_mcc_role *ref = &mcc->role_ref;
1808 struct rtw89_mcc_role *aux = &mcc->role_aux;
1809 struct rtw89_mcc_config *config = &mcc->config;
1810 struct rtw89_mcc_pattern *pattern = &config->pattern;
1811 struct rtw89_mcc_sync *sync = &config->sync;
1812 struct rtw89_fw_mrc_start_arg start_arg = {};
1813 struct rtw89_fw_mrc_add_arg add_arg = {};
1816 BUILD_BUG_ON(RTW89_MAC_MRC_MAX_ADD_SLOT_NUM <
1817 NUM_OF_RTW89_MCC_ROLES + 1 /* bt role */);
1820 start_arg.old_sch_idx = mcc->group;
1821 start_arg.action = RTW89_H2C_MRC_START_ACTION_REPLACE_OLD;
1822 mcc->group = RTW89_MCC_NEXT_GROUP(mcc->group);
1825 add_arg.sch_idx = mcc->group;
1826 add_arg.sch_type = RTW89_H2C_MRC_SCH_BAND0_ONLY;
1828 switch (pattern->plan) {
1829 case RTW89_MCC_PLAN_TAIL_BT:
1830 __mrc_fw_add_role(rtwdev, ref, &add_arg, 0);
1831 __mrc_fw_add_role(rtwdev, aux, &add_arg, 1);
1832 __mrc_fw_add_bt_role(rtwdev, &add_arg, 2);
1834 add_arg.slot_num = 3;
1835 add_arg.btc_in_sch = true;
1837 case RTW89_MCC_PLAN_MID_BT:
1838 __mrc_fw_add_role(rtwdev, ref, &add_arg, 0);
1839 __mrc_fw_add_bt_role(rtwdev, &add_arg, 1);
1840 __mrc_fw_add_role(rtwdev, aux, &add_arg, 2);
1842 add_arg.slot_num = 3;
1843 add_arg.btc_in_sch = true;
1845 case RTW89_MCC_PLAN_NO_BT:
1846 __mrc_fw_add_role(rtwdev, ref, &add_arg, 0);
1847 __mrc_fw_add_role(rtwdev, aux, &add_arg, 1);
1849 add_arg.slot_num = 2;
1850 add_arg.btc_in_sch = false;
1853 rtw89_warn(rtwdev, "MCC unknown plan: %d\n", pattern->plan);
1857 __mrc_fw_add_courtesy(rtwdev, &add_arg);
1859 ret = rtw89_fw_h2c_mrc_add(rtwdev, &add_arg);
1861 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1862 "MRC h2c failed to trigger add: %d\n", ret);
1867 struct rtw89_fw_mrc_sync_arg sync_arg = {
1868 .offset = sync->offset,
1870 .band = sync->band_src,
1871 .port = sync->port_src,
1874 .band = sync->band_tgt,
1875 .port = sync->port_tgt,
1879 ret = rtw89_fw_h2c_mrc_sync(rtwdev, &sync_arg);
1881 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1882 "MRC h2c failed to trigger sync: %d\n", ret);
1887 start_arg.sch_idx = mcc->group;
1888 start_arg.start_tsf = config->start_tsf;
1890 ret = rtw89_fw_h2c_mrc_start(rtwdev, &start_arg);
1892 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1893 "MRC h2c failed to trigger start: %d\n", ret);
1900 static int __mcc_fw_set_duration_no_bt(struct rtw89_dev *rtwdev, bool sync_changed)
1902 struct rtw89_mcc_info *mcc = &rtwdev->mcc;
1903 struct rtw89_mcc_config *config = &mcc->config;
1904 struct rtw89_mcc_sync *sync = &config->sync;
1905 struct rtw89_mcc_role *ref = &mcc->role_ref;
1906 struct rtw89_mcc_role *aux = &mcc->role_aux;
1907 struct rtw89_fw_mcc_duration req = {
1908 .group = mcc->group,
1909 .btc_in_group = false,
1910 .start_macid = ref->rtwvif_link->mac_id,
1911 .macid_x = ref->rtwvif_link->mac_id,
1912 .macid_y = aux->rtwvif_link->mac_id,
1913 .duration_x = ref->duration,
1914 .duration_y = aux->duration,
1915 .start_tsf_high = config->start_tsf >> 32,
1916 .start_tsf_low = config->start_tsf,
1920 ret = rtw89_fw_h2c_mcc_set_duration(rtwdev, &req);
1922 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1923 "MCC h2c failed to set duration: %d\n", ret);
1927 if (!sync->enable || !sync_changed)
1930 ret = rtw89_fw_h2c_mcc_sync(rtwdev, mcc->group, sync->macid_src,
1931 sync->macid_tgt, sync->offset);
1933 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1934 "MCC h2c failed to trigger sync: %d\n", ret);
1941 static int __mrc_fw_set_duration_no_bt(struct rtw89_dev *rtwdev, bool sync_changed)
1943 struct rtw89_mcc_info *mcc = &rtwdev->mcc;
1944 struct rtw89_mcc_config *config = &mcc->config;
1945 struct rtw89_mcc_sync *sync = &config->sync;
1946 struct rtw89_mcc_role *ref = &mcc->role_ref;
1947 struct rtw89_mcc_role *aux = &mcc->role_aux;
1948 struct rtw89_fw_mrc_upd_duration_arg dur_arg = {
1949 .sch_idx = mcc->group,
1950 .start_tsf = config->start_tsf,
1953 .slot_idx = ref->slot_idx,
1954 .duration = ref->duration,
1957 .slot_idx = aux->slot_idx,
1958 .duration = aux->duration,
1961 struct rtw89_fw_mrc_sync_arg sync_arg = {
1962 .offset = sync->offset,
1964 .band = sync->band_src,
1965 .port = sync->port_src,
1968 .band = sync->band_tgt,
1969 .port = sync->port_tgt,
1975 ret = rtw89_fw_h2c_mrc_upd_duration(rtwdev, &dur_arg);
1977 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1978 "MRC h2c failed to update duration: %d\n", ret);
1982 if (!sync->enable || !sync_changed)
1985 ret = rtw89_fw_h2c_mrc_sync(rtwdev, &sync_arg);
1987 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
1988 "MRC h2c failed to trigger sync: %d\n", ret);
1995 static void rtw89_mcc_handle_beacon_noa(struct rtw89_dev *rtwdev, bool enable)
1997 struct rtw89_mcc_info *mcc = &rtwdev->mcc;
1998 struct rtw89_mcc_role *ref = &mcc->role_ref;
1999 struct rtw89_mcc_role *aux = &mcc->role_aux;
2000 struct rtw89_mcc_config *config = &mcc->config;
2001 struct rtw89_mcc_pattern *pattern = &config->pattern;
2002 struct rtw89_mcc_sync *sync = &config->sync;
2003 struct ieee80211_p2p_noa_desc noa_desc = {};
2004 u64 start_time = config->start_tsf;
2005 u32 interval = config->mcc_interval;
2006 struct rtw89_vif_link *rtwvif_go;
2009 if (mcc->mode != RTW89_MCC_MODE_GO_STA)
2013 rtwvif_go = ref->rtwvif_link;
2014 start_time += ieee80211_tu_to_usec(ref->duration);
2015 duration = config->mcc_interval - ref->duration;
2016 } else if (aux->is_go) {
2017 rtwvif_go = aux->rtwvif_link;
2018 start_time += ieee80211_tu_to_usec(pattern->tob_ref) +
2019 ieee80211_tu_to_usec(config->beacon_offset) +
2020 ieee80211_tu_to_usec(pattern->toa_aux);
2021 duration = config->mcc_interval - aux->duration;
2023 /* convert time domain from sta(ref) to GO(aux) */
2024 start_time += ieee80211_tu_to_usec(sync->offset);
2026 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
2027 "MCC find no GO: skip updating beacon NoA\n");
2031 rtw89_p2p_noa_renew(rtwvif_go);
2034 noa_desc.start_time = cpu_to_le32(start_time);
2035 noa_desc.interval = cpu_to_le32(ieee80211_tu_to_usec(interval));
2036 noa_desc.duration = cpu_to_le32(ieee80211_tu_to_usec(duration));
2037 noa_desc.count = 255;
2038 rtw89_p2p_noa_append(rtwvif_go, &noa_desc);
2041 /* without chanctx, we cannot get beacon from mac80211 stack */
2042 if (!rtwvif_go->chanctx_assigned)
2045 rtw89_chip_h2c_update_beacon(rtwdev, rtwvif_go);
2048 static void rtw89_mcc_start_beacon_noa(struct rtw89_dev *rtwdev)
2050 struct rtw89_mcc_info *mcc = &rtwdev->mcc;
2051 struct rtw89_mcc_role *ref = &mcc->role_ref;
2052 struct rtw89_mcc_role *aux = &mcc->role_aux;
2054 if (mcc->mode != RTW89_MCC_MODE_GO_STA)
2058 rtw89_fw_h2c_tsf32_toggle(rtwdev, ref->rtwvif_link, true);
2059 else if (aux->is_go)
2060 rtw89_fw_h2c_tsf32_toggle(rtwdev, aux->rtwvif_link, true);
2062 rtw89_mcc_handle_beacon_noa(rtwdev, true);
2065 static void rtw89_mcc_stop_beacon_noa(struct rtw89_dev *rtwdev)
2067 struct rtw89_mcc_info *mcc = &rtwdev->mcc;
2068 struct rtw89_mcc_role *ref = &mcc->role_ref;
2069 struct rtw89_mcc_role *aux = &mcc->role_aux;
2071 if (mcc->mode != RTW89_MCC_MODE_GO_STA)
2075 rtw89_fw_h2c_tsf32_toggle(rtwdev, ref->rtwvif_link, false);
2076 else if (aux->is_go)
2077 rtw89_fw_h2c_tsf32_toggle(rtwdev, aux->rtwvif_link, false);
2079 rtw89_mcc_handle_beacon_noa(rtwdev, false);
2082 static int rtw89_mcc_start(struct rtw89_dev *rtwdev)
2084 struct rtw89_mcc_info *mcc = &rtwdev->mcc;
2085 struct rtw89_mcc_role *ref = &mcc->role_ref;
2086 struct rtw89_mcc_role *aux = &mcc->role_aux;
2089 if (rtwdev->scanning)
2090 rtw89_hw_scan_abort(rtwdev, rtwdev->scan_info.scanning_vif);
2092 rtw89_leave_lps(rtwdev);
2094 rtw89_debug(rtwdev, RTW89_DBG_CHAN, "MCC start\n");
2096 ret = rtw89_mcc_fill_all_roles(rtwdev);
2100 if (ref->is_go || aux->is_go)
2101 mcc->mode = RTW89_MCC_MODE_GO_STA;
2103 mcc->mode = RTW89_MCC_MODE_GC_STA;
2105 rtw89_debug(rtwdev, RTW89_DBG_CHAN, "MCC sel mode: %d\n", mcc->mode);
2107 mcc->group = RTW89_MCC_DFLT_GROUP;
2109 ret = rtw89_mcc_fill_config(rtwdev);
2113 if (rtw89_concurrent_via_mrc(rtwdev))
2114 ret = __mrc_fw_start(rtwdev, false);
2116 ret = __mcc_fw_start(rtwdev, false);
2121 rtw89_chanctx_notify(rtwdev, RTW89_CHANCTX_STATE_MCC_START);
2123 rtw89_mcc_start_beacon_noa(rtwdev);
2127 struct rtw89_mcc_stop_sel {
2132 static void rtw89_mcc_stop_sel_fill(struct rtw89_mcc_stop_sel *sel,
2133 const struct rtw89_mcc_role *mcc_role)
2135 sel->mac_id = mcc_role->rtwvif_link->mac_id;
2136 sel->slot_idx = mcc_role->slot_idx;
2139 static int rtw89_mcc_stop_sel_iterator(struct rtw89_dev *rtwdev,
2140 struct rtw89_mcc_role *mcc_role,
2141 unsigned int ordered_idx,
2144 struct rtw89_mcc_stop_sel *sel = data;
2146 if (!mcc_role->rtwvif_link->chanctx_assigned)
2149 rtw89_mcc_stop_sel_fill(sel, mcc_role);
2150 return 1; /* break iteration */
2153 static void rtw89_mcc_stop(struct rtw89_dev *rtwdev)
2155 struct rtw89_mcc_info *mcc = &rtwdev->mcc;
2156 struct rtw89_mcc_role *ref = &mcc->role_ref;
2157 struct rtw89_mcc_stop_sel sel;
2160 /* by default, stop at ref */
2161 rtw89_mcc_stop_sel_fill(&sel, ref);
2162 rtw89_iterate_mcc_roles(rtwdev, rtw89_mcc_stop_sel_iterator, &sel);
2164 rtw89_debug(rtwdev, RTW89_DBG_CHAN, "MCC stop at <macid %d>\n", sel.mac_id);
2166 if (rtw89_concurrent_via_mrc(rtwdev)) {
2167 ret = rtw89_fw_h2c_mrc_del(rtwdev, mcc->group, sel.slot_idx);
2169 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
2170 "MRC h2c failed to trigger del: %d\n", ret);
2172 ret = rtw89_fw_h2c_stop_mcc(rtwdev, mcc->group,
2175 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
2176 "MCC h2c failed to trigger stop: %d\n", ret);
2178 ret = rtw89_fw_h2c_del_mcc_group(rtwdev, mcc->group, true);
2180 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
2181 "MCC h2c failed to delete group: %d\n", ret);
2184 rtw89_chanctx_notify(rtwdev, RTW89_CHANCTX_STATE_MCC_STOP);
2186 rtw89_mcc_stop_beacon_noa(rtwdev);
2189 static int rtw89_mcc_update(struct rtw89_dev *rtwdev)
2191 struct rtw89_mcc_info *mcc = &rtwdev->mcc;
2192 struct rtw89_mcc_config *config = &mcc->config;
2193 struct rtw89_mcc_config old_cfg = *config;
2197 if (rtwdev->scanning)
2198 rtw89_hw_scan_abort(rtwdev, rtwdev->scan_info.scanning_vif);
2200 rtw89_debug(rtwdev, RTW89_DBG_CHAN, "MCC update\n");
2202 ret = rtw89_mcc_fill_config(rtwdev);
2206 if (old_cfg.pattern.plan != RTW89_MCC_PLAN_NO_BT ||
2207 config->pattern.plan != RTW89_MCC_PLAN_NO_BT) {
2208 if (rtw89_concurrent_via_mrc(rtwdev))
2209 ret = __mrc_fw_start(rtwdev, true);
2211 ret = __mcc_fw_start(rtwdev, true);
2216 if (memcmp(&old_cfg.sync, &config->sync, sizeof(old_cfg.sync)) == 0)
2217 sync_changed = false;
2219 sync_changed = true;
2221 if (rtw89_concurrent_via_mrc(rtwdev))
2222 ret = __mrc_fw_set_duration_no_bt(rtwdev, sync_changed);
2224 ret = __mcc_fw_set_duration_no_bt(rtwdev, sync_changed);
2230 rtw89_mcc_handle_beacon_noa(rtwdev, true);
2234 static void rtw89_mcc_track(struct rtw89_dev *rtwdev)
2236 struct rtw89_mcc_info *mcc = &rtwdev->mcc;
2237 struct rtw89_mcc_config *config = &mcc->config;
2238 struct rtw89_mcc_pattern *pattern = &config->pattern;
2243 if (mcc->mode != RTW89_MCC_MODE_GC_STA)
2246 bcn_ofst = rtw89_mcc_get_bcn_ofst(rtwdev);
2247 if (bcn_ofst > config->beacon_offset) {
2248 diff = bcn_ofst - config->beacon_offset;
2249 if (pattern->tob_aux < 0)
2250 tolerance = -pattern->tob_aux;
2252 tolerance = pattern->toa_aux;
2254 diff = config->beacon_offset - bcn_ofst;
2255 if (pattern->toa_aux < 0)
2256 tolerance = -pattern->toa_aux;
2258 tolerance = pattern->tob_aux;
2261 if (diff <= tolerance)
2264 rtw89_queue_chanctx_change(rtwdev, RTW89_CHANCTX_BCN_OFFSET_CHANGE);
2267 static int __mcc_fw_upd_macid_bitmap(struct rtw89_dev *rtwdev,
2268 struct rtw89_mcc_role *upd)
2270 struct rtw89_mcc_info *mcc = &rtwdev->mcc;
2273 ret = rtw89_fw_h2c_mcc_macid_bitmap(rtwdev, mcc->group,
2274 upd->rtwvif_link->mac_id,
2277 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
2278 "MCC h2c failed to update macid bitmap: %d\n", ret);
2285 static int __mrc_fw_upd_macid_bitmap(struct rtw89_dev *rtwdev,
2286 struct rtw89_mcc_role *cur,
2287 struct rtw89_mcc_role *upd)
2289 struct rtw89_mcc_info *mcc = &rtwdev->mcc;
2290 struct rtw89_fw_mrc_upd_bitmap_arg arg = {};
2291 u32 old = rtw89_mcc_role_fw_macid_bitmap_to_u32(cur);
2292 u32 new = rtw89_mcc_role_fw_macid_bitmap_to_u32(upd);
2293 u32 add = new & ~old;
2294 u32 del = old & ~new;
2298 arg.sch_idx = mcc->group;
2299 arg.macid = upd->rtwvif_link->mac_id;
2301 for (i = 0; i < 32; i++) {
2303 arg.client_macid = i;
2304 arg.action = RTW89_H2C_MRC_UPD_BITMAP_ACTION_ADD;
2306 ret = rtw89_fw_h2c_mrc_upd_bitmap(rtwdev, &arg);
2312 for (i = 0; i < 32; i++) {
2314 arg.client_macid = i;
2315 arg.action = RTW89_H2C_MRC_UPD_BITMAP_ACTION_DEL;
2317 ret = rtw89_fw_h2c_mrc_upd_bitmap(rtwdev, &arg);
2326 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
2327 "MRC h2c failed to update bitmap: %d\n", ret);
2331 static int rtw89_mcc_upd_map_iterator(struct rtw89_dev *rtwdev,
2332 struct rtw89_mcc_role *mcc_role,
2333 unsigned int ordered_idx,
2336 struct rtw89_mcc_role upd = {
2337 .rtwvif_link = mcc_role->rtwvif_link,
2341 if (!mcc_role->is_go)
2344 rtw89_mcc_fill_role_macid_bitmap(rtwdev, &upd);
2345 if (memcmp(mcc_role->macid_bitmap, upd.macid_bitmap,
2346 sizeof(mcc_role->macid_bitmap)) == 0)
2349 if (rtw89_concurrent_via_mrc(rtwdev))
2350 ret = __mrc_fw_upd_macid_bitmap(rtwdev, mcc_role, &upd);
2352 ret = __mcc_fw_upd_macid_bitmap(rtwdev, &upd);
2357 memcpy(mcc_role->macid_bitmap, upd.macid_bitmap,
2358 sizeof(mcc_role->macid_bitmap));
2362 static void rtw89_mcc_update_macid_bitmap(struct rtw89_dev *rtwdev)
2364 struct rtw89_mcc_info *mcc = &rtwdev->mcc;
2366 if (mcc->mode != RTW89_MCC_MODE_GO_STA)
2369 rtw89_iterate_mcc_roles(rtwdev, rtw89_mcc_upd_map_iterator, NULL);
2372 static int rtw89_mcc_upd_lmt_iterator(struct rtw89_dev *rtwdev,
2373 struct rtw89_mcc_role *mcc_role,
2374 unsigned int ordered_idx,
2377 memset(&mcc_role->limit, 0, sizeof(mcc_role->limit));
2378 rtw89_mcc_fill_role_limit(rtwdev, mcc_role);
2382 static void rtw89_mcc_update_limit(struct rtw89_dev *rtwdev)
2384 struct rtw89_mcc_info *mcc = &rtwdev->mcc;
2386 if (mcc->mode != RTW89_MCC_MODE_GC_STA)
2389 rtw89_iterate_mcc_roles(rtwdev, rtw89_mcc_upd_lmt_iterator, NULL);
2392 void rtw89_chanctx_work(struct work_struct *work)
2394 struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
2396 struct rtw89_hal *hal = &rtwdev->hal;
2397 bool update_mcc_pattern = false;
2398 enum rtw89_entity_mode mode;
2403 mutex_lock(&rtwdev->mutex);
2405 if (hal->entity_pause) {
2406 mutex_unlock(&rtwdev->mutex);
2410 for (i = 0; i < NUM_OF_RTW89_CHANCTX_CHANGES; i++) {
2411 if (test_and_clear_bit(i, hal->changes))
2415 mode = rtw89_get_entity_mode(rtwdev);
2417 case RTW89_ENTITY_MODE_MCC_PREPARE:
2418 rtw89_set_entity_mode(rtwdev, RTW89_ENTITY_MODE_MCC);
2419 rtw89_set_channel(rtwdev);
2421 ret = rtw89_mcc_start(rtwdev);
2423 rtw89_warn(rtwdev, "failed to start MCC: %d\n", ret);
2425 case RTW89_ENTITY_MODE_MCC:
2426 if (changed & BIT(RTW89_CHANCTX_BCN_OFFSET_CHANGE) ||
2427 changed & BIT(RTW89_CHANCTX_P2P_PS_CHANGE) ||
2428 changed & BIT(RTW89_CHANCTX_BT_SLOT_CHANGE) ||
2429 changed & BIT(RTW89_CHANCTX_TSF32_TOGGLE_CHANGE))
2430 update_mcc_pattern = true;
2431 if (changed & BIT(RTW89_CHANCTX_REMOTE_STA_CHANGE))
2432 rtw89_mcc_update_macid_bitmap(rtwdev);
2433 if (changed & BIT(RTW89_CHANCTX_P2P_PS_CHANGE))
2434 rtw89_mcc_update_limit(rtwdev);
2435 if (changed & BIT(RTW89_CHANCTX_BT_SLOT_CHANGE))
2436 rtw89_mcc_fill_bt_role(rtwdev);
2437 if (update_mcc_pattern) {
2438 ret = rtw89_mcc_update(rtwdev);
2440 rtw89_warn(rtwdev, "failed to update MCC: %d\n",
2448 mutex_unlock(&rtwdev->mutex);
2451 void rtw89_queue_chanctx_change(struct rtw89_dev *rtwdev,
2452 enum rtw89_chanctx_changes change)
2454 struct rtw89_hal *hal = &rtwdev->hal;
2455 enum rtw89_entity_mode mode;
2458 mode = rtw89_get_entity_mode(rtwdev);
2462 case RTW89_ENTITY_MODE_MCC_PREPARE:
2463 delay = ieee80211_tu_to_usec(RTW89_CHANCTX_TIME_MCC_PREPARE);
2465 case RTW89_ENTITY_MODE_MCC:
2466 delay = ieee80211_tu_to_usec(RTW89_CHANCTX_TIME_MCC);
2470 if (change != RTW89_CHANCTX_CHANGE_DFLT) {
2471 rtw89_debug(rtwdev, RTW89_DBG_CHAN, "set chanctx change %d\n",
2473 set_bit(change, hal->changes);
2476 rtw89_debug(rtwdev, RTW89_DBG_CHAN,
2477 "queue chanctx work for mode %d with delay %d us\n",
2479 ieee80211_queue_delayed_work(rtwdev->hw, &rtwdev->chanctx_work,
2480 usecs_to_jiffies(delay));
2483 void rtw89_queue_chanctx_work(struct rtw89_dev *rtwdev)
2485 rtw89_queue_chanctx_change(rtwdev, RTW89_CHANCTX_CHANGE_DFLT);
2488 void rtw89_chanctx_track(struct rtw89_dev *rtwdev)
2490 struct rtw89_hal *hal = &rtwdev->hal;
2491 enum rtw89_entity_mode mode;
2493 lockdep_assert_held(&rtwdev->mutex);
2495 if (hal->entity_pause)
2498 mode = rtw89_get_entity_mode(rtwdev);
2500 case RTW89_ENTITY_MODE_MCC:
2501 rtw89_mcc_track(rtwdev);
2508 void rtw89_chanctx_pause(struct rtw89_dev *rtwdev,
2509 enum rtw89_chanctx_pause_reasons rsn)
2511 struct rtw89_hal *hal = &rtwdev->hal;
2512 enum rtw89_entity_mode mode;
2514 lockdep_assert_held(&rtwdev->mutex);
2516 if (hal->entity_pause)
2519 rtw89_debug(rtwdev, RTW89_DBG_CHAN, "chanctx pause (rsn: %d)\n", rsn);
2521 mode = rtw89_get_entity_mode(rtwdev);
2523 case RTW89_ENTITY_MODE_MCC:
2524 rtw89_mcc_stop(rtwdev);
2530 hal->entity_pause = true;
2533 void rtw89_chanctx_proceed(struct rtw89_dev *rtwdev)
2535 struct rtw89_hal *hal = &rtwdev->hal;
2536 enum rtw89_entity_mode mode;
2539 lockdep_assert_held(&rtwdev->mutex);
2541 if (!hal->entity_pause)
2544 rtw89_debug(rtwdev, RTW89_DBG_CHAN, "chanctx proceed\n");
2546 hal->entity_pause = false;
2547 rtw89_set_channel(rtwdev);
2549 mode = rtw89_get_entity_mode(rtwdev);
2551 case RTW89_ENTITY_MODE_MCC:
2552 ret = rtw89_mcc_start(rtwdev);
2554 rtw89_warn(rtwdev, "failed to start MCC: %d\n", ret);
2560 rtw89_queue_chanctx_work(rtwdev);
2563 static void __rtw89_swap_chanctx(struct rtw89_vif *rtwvif,
2564 enum rtw89_chanctx_idx idx1,
2565 enum rtw89_chanctx_idx idx2)
2567 struct rtw89_vif_link *rtwvif_link;
2568 unsigned int link_id;
2570 rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) {
2571 if (!rtwvif_link->chanctx_assigned)
2574 if (rtwvif_link->chanctx_idx == idx1)
2575 rtwvif_link->chanctx_idx = idx2;
2576 else if (rtwvif_link->chanctx_idx == idx2)
2577 rtwvif_link->chanctx_idx = idx1;
2581 static void rtw89_swap_chanctx(struct rtw89_dev *rtwdev,
2582 enum rtw89_chanctx_idx idx1,
2583 enum rtw89_chanctx_idx idx2)
2585 struct rtw89_hal *hal = &rtwdev->hal;
2586 struct rtw89_vif *rtwvif;
2592 hal->chanctx[idx1].cfg->idx = idx2;
2593 hal->chanctx[idx2].cfg->idx = idx1;
2595 swap(hal->chanctx[idx1], hal->chanctx[idx2]);
2597 rtw89_for_each_rtwvif(rtwdev, rtwvif)
2598 __rtw89_swap_chanctx(rtwvif, idx1, idx2);
2600 cur = atomic_read(&hal->roc_chanctx_idx);
2602 atomic_set(&hal->roc_chanctx_idx, idx2);
2603 else if (cur == idx2)
2604 atomic_set(&hal->roc_chanctx_idx, idx1);
2607 int rtw89_chanctx_ops_add(struct rtw89_dev *rtwdev,
2608 struct ieee80211_chanctx_conf *ctx)
2610 struct rtw89_hal *hal = &rtwdev->hal;
2611 struct rtw89_chanctx_cfg *cfg = (struct rtw89_chanctx_cfg *)ctx->drv_priv;
2612 const struct rtw89_chip_info *chip = rtwdev->chip;
2615 idx = find_first_zero_bit(hal->entity_map, NUM_OF_RTW89_CHANCTX);
2616 if (idx >= chip->support_chanctx_num)
2619 rtw89_config_entity_chandef(rtwdev, idx, &ctx->def);
2622 hal->chanctx[idx].cfg = cfg;
2626 void rtw89_chanctx_ops_remove(struct rtw89_dev *rtwdev,
2627 struct ieee80211_chanctx_conf *ctx)
2629 struct rtw89_hal *hal = &rtwdev->hal;
2630 struct rtw89_chanctx_cfg *cfg = (struct rtw89_chanctx_cfg *)ctx->drv_priv;
2632 clear_bit(cfg->idx, hal->entity_map);
2635 void rtw89_chanctx_ops_change(struct rtw89_dev *rtwdev,
2636 struct ieee80211_chanctx_conf *ctx,
2639 struct rtw89_chanctx_cfg *cfg = (struct rtw89_chanctx_cfg *)ctx->drv_priv;
2642 if (changed & IEEE80211_CHANCTX_CHANGE_WIDTH) {
2643 rtw89_config_entity_chandef(rtwdev, idx, &ctx->def);
2644 rtw89_set_channel(rtwdev);
2648 int rtw89_chanctx_ops_assign_vif(struct rtw89_dev *rtwdev,
2649 struct rtw89_vif_link *rtwvif_link,
2650 struct ieee80211_chanctx_conf *ctx)
2652 struct rtw89_chanctx_cfg *cfg = (struct rtw89_chanctx_cfg *)ctx->drv_priv;
2653 struct rtw89_vif *rtwvif = rtwvif_link->rtwvif;
2654 struct rtw89_hal *hal = &rtwdev->hal;
2655 struct rtw89_entity_mgnt *mgnt = &hal->entity_mgnt;
2656 struct rtw89_entity_weight w = {};
2658 rtwvif_link->chanctx_idx = cfg->idx;
2659 rtwvif_link->chanctx_assigned = true;
2662 if (list_empty(&rtwvif->mgnt_entry))
2663 list_add_tail(&rtwvif->mgnt_entry, &mgnt->active_list);
2665 if (cfg->idx == RTW89_CHANCTX_0)
2668 rtw89_entity_calculate_weight(rtwdev, &w);
2669 if (w.active_chanctxs != 1)
2672 /* put the first active chanctx at RTW89_CHANCTX_0 */
2673 rtw89_swap_chanctx(rtwdev, cfg->idx, RTW89_CHANCTX_0);
2676 return rtw89_set_channel(rtwdev);
2679 void rtw89_chanctx_ops_unassign_vif(struct rtw89_dev *rtwdev,
2680 struct rtw89_vif_link *rtwvif_link,
2681 struct ieee80211_chanctx_conf *ctx)
2683 struct rtw89_chanctx_cfg *cfg = (struct rtw89_chanctx_cfg *)ctx->drv_priv;
2684 struct rtw89_vif *rtwvif = rtwvif_link->rtwvif;
2685 struct rtw89_hal *hal = &rtwdev->hal;
2686 enum rtw89_chanctx_idx roll;
2687 enum rtw89_entity_mode cur;
2688 enum rtw89_entity_mode new;
2691 rtwvif_link->chanctx_idx = RTW89_CHANCTX_0;
2692 rtwvif_link->chanctx_assigned = false;
2695 if (!rtw89_vif_is_active_role(rtwvif))
2696 list_del_init(&rtwvif->mgnt_entry);
2698 if (cfg->ref_count != 0)
2701 if (cfg->idx != RTW89_CHANCTX_0)
2704 roll = find_next_bit(hal->entity_map, NUM_OF_RTW89_CHANCTX,
2706 /* Follow rtw89_config_default_chandef() when rtw89_entity_recalc(). */
2707 if (roll == NUM_OF_RTW89_CHANCTX)
2710 /* RTW89_CHANCTX_0 is going to release, and another exists.
2711 * Make another roll down to RTW89_CHANCTX_0 to replace.
2713 rtw89_swap_chanctx(rtwdev, cfg->idx, roll);
2716 if (!hal->entity_pause) {
2717 cur = rtw89_get_entity_mode(rtwdev);
2719 case RTW89_ENTITY_MODE_MCC:
2720 rtw89_mcc_stop(rtwdev);
2727 ret = rtw89_set_channel(rtwdev);
2731 if (hal->entity_pause)
2734 new = rtw89_get_entity_mode(rtwdev);
2736 case RTW89_ENTITY_MODE_MCC:
2737 /* re-plan MCC for chanctx changes. */
2738 ret = rtw89_mcc_start(rtwdev);
2740 rtw89_warn(rtwdev, "failed to start MCC: %d\n", ret);