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