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