File Index
Files and directories
Sign in
FILE

chan.c

File preview with syntax highlighting.

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