Linux Audio

Check our new training course

Real-Time Linux with PREEMPT_RT training

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