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 "debug.h"
7#include "fw.h"
8#include "ps.h"
9#include "util.h"
10
11static enum rtw89_subband rtw89_get_subband_type(enum rtw89_band band,
12						 u8 center_chan)
13{
14	switch (band) {
15	default:
16	case RTW89_BAND_2G:
17		switch (center_chan) {
18		default:
19		case 1 ... 14:
20			return RTW89_CH_2G;
21		}
22	case RTW89_BAND_5G:
23		switch (center_chan) {
24		default:
25		case 36 ... 64:
26			return RTW89_CH_5G_BAND_1;
27		case 100 ... 144:
28			return RTW89_CH_5G_BAND_3;
29		case 149 ... 177:
30			return RTW89_CH_5G_BAND_4;
31		}
32	case RTW89_BAND_6G:
33		switch (center_chan) {
34		default:
35		case 1 ... 29:
36			return RTW89_CH_6G_BAND_IDX0;
37		case 33 ... 61:
38			return RTW89_CH_6G_BAND_IDX1;
39		case 65 ... 93:
40			return RTW89_CH_6G_BAND_IDX2;
41		case 97 ... 125:
42			return RTW89_CH_6G_BAND_IDX3;
43		case 129 ... 157:
44			return RTW89_CH_6G_BAND_IDX4;
45		case 161 ... 189:
46			return RTW89_CH_6G_BAND_IDX5;
47		case 193 ... 221:
48			return RTW89_CH_6G_BAND_IDX6;
49		case 225 ... 253:
50			return RTW89_CH_6G_BAND_IDX7;
51		}
52	}
53}
54
55static enum rtw89_sc_offset rtw89_get_primary_chan_idx(enum rtw89_bandwidth bw,
56						       u32 center_freq,
57						       u32 primary_freq)
58{
59	u8 primary_chan_idx;
60	u32 offset;
61
62	switch (bw) {
63	default:
64	case RTW89_CHANNEL_WIDTH_20:
65		primary_chan_idx = RTW89_SC_DONT_CARE;
66		break;
67	case RTW89_CHANNEL_WIDTH_40:
68		if (primary_freq > center_freq)
69			primary_chan_idx = RTW89_SC_20_UPPER;
70		else
71			primary_chan_idx = RTW89_SC_20_LOWER;
72		break;
73	case RTW89_CHANNEL_WIDTH_80:
74	case RTW89_CHANNEL_WIDTH_160:
75		if (primary_freq > center_freq) {
76			offset = (primary_freq - center_freq - 10) / 20;
77			primary_chan_idx = RTW89_SC_20_UPPER + offset * 2;
78		} else {
79			offset = (center_freq - primary_freq - 10) / 20;
80			primary_chan_idx = RTW89_SC_20_LOWER + offset * 2;
81		}
82		break;
83	}
84
85	return primary_chan_idx;
86}
87
88void rtw89_chan_create(struct rtw89_chan *chan, u8 center_chan, u8 primary_chan,
89		       enum rtw89_band band, enum rtw89_bandwidth bandwidth)
90{
91	enum nl80211_band nl_band = rtw89_hw_to_nl80211_band(band);
92	u32 center_freq, primary_freq;
93
94	memset(chan, 0, sizeof(*chan));
95	chan->channel = center_chan;
96	chan->primary_channel = primary_chan;
97	chan->band_type = band;
98	chan->band_width = bandwidth;
99
100	center_freq = ieee80211_channel_to_frequency(center_chan, nl_band);
101	primary_freq = ieee80211_channel_to_frequency(primary_chan, nl_band);
102
103	chan->freq = center_freq;
104	chan->subband_type = rtw89_get_subband_type(band, center_chan);
105	chan->pri_ch_idx = rtw89_get_primary_chan_idx(bandwidth, center_freq,
106						      primary_freq);
107}
108
109bool rtw89_assign_entity_chan(struct rtw89_dev *rtwdev,
110			      enum rtw89_sub_entity_idx idx,
111			      const struct rtw89_chan *new)
112{
113	struct rtw89_hal *hal = &rtwdev->hal;
114	struct rtw89_chan *chan = &hal->sub[idx].chan;
115	struct rtw89_chan_rcd *rcd = &hal->sub[idx].rcd;
116	bool band_changed;
117
118	rcd->prev_primary_channel = chan->primary_channel;
119	rcd->prev_band_type = chan->band_type;
120	band_changed = new->band_type != chan->band_type;
121	rcd->band_changed = band_changed;
122
123	*chan = *new;
124	return band_changed;
125}
126
127static void __rtw89_config_entity_chandef(struct rtw89_dev *rtwdev,
128					  enum rtw89_sub_entity_idx idx,
129					  const struct cfg80211_chan_def *chandef,
130					  bool from_stack)
131{
132	struct rtw89_hal *hal = &rtwdev->hal;
133
134	hal->sub[idx].chandef = *chandef;
135
136	if (from_stack)
137		set_bit(idx, hal->entity_map);
138}
139
140void rtw89_config_entity_chandef(struct rtw89_dev *rtwdev,
141				 enum rtw89_sub_entity_idx idx,
142				 const struct cfg80211_chan_def *chandef)
143{
144	__rtw89_config_entity_chandef(rtwdev, idx, chandef, true);
145}
146
147void rtw89_config_roc_chandef(struct rtw89_dev *rtwdev,
148			      enum rtw89_sub_entity_idx idx,
149			      const struct cfg80211_chan_def *chandef)
150{
151	struct rtw89_hal *hal = &rtwdev->hal;
152	enum rtw89_sub_entity_idx cur;
153
154	if (chandef) {
155		cur = atomic_cmpxchg(&hal->roc_entity_idx,
156				     RTW89_SUB_ENTITY_IDLE, idx);
157		if (cur != RTW89_SUB_ENTITY_IDLE) {
158			rtw89_debug(rtwdev, RTW89_DBG_TXRX,
159				    "ROC still processing on entity %d\n", idx);
160			return;
161		}
162
163		hal->roc_chandef = *chandef;
164	} else {
165		cur = atomic_cmpxchg(&hal->roc_entity_idx, idx,
166				     RTW89_SUB_ENTITY_IDLE);
167		if (cur == idx)
168			return;
169
170		if (cur == RTW89_SUB_ENTITY_IDLE)
171			rtw89_debug(rtwdev, RTW89_DBG_TXRX,
172				    "ROC already finished on entity %d\n", idx);
173		else
174			rtw89_debug(rtwdev, RTW89_DBG_TXRX,
175				    "ROC is processing on entity %d\n", cur);
176	}
177}
178
179static void rtw89_config_default_chandef(struct rtw89_dev *rtwdev)
180{
181	struct cfg80211_chan_def chandef = {0};
182
183	rtw89_get_default_chandef(&chandef);
184	__rtw89_config_entity_chandef(rtwdev, RTW89_SUB_ENTITY_0, &chandef, false);
185}
186
187void rtw89_entity_init(struct rtw89_dev *rtwdev)
188{
189	struct rtw89_hal *hal = &rtwdev->hal;
190
191	bitmap_zero(hal->entity_map, NUM_OF_RTW89_SUB_ENTITY);
192	atomic_set(&hal->roc_entity_idx, RTW89_SUB_ENTITY_IDLE);
193	rtw89_config_default_chandef(rtwdev);
194}
195
196enum rtw89_entity_mode rtw89_entity_recalc(struct rtw89_dev *rtwdev)
197{
198	struct rtw89_hal *hal = &rtwdev->hal;
199	const struct cfg80211_chan_def *chandef;
200	enum rtw89_entity_mode mode;
201	struct rtw89_chan chan;
202	u8 weight;
203	u8 last;
204	u8 idx;
205
206	weight = bitmap_weight(hal->entity_map, NUM_OF_RTW89_SUB_ENTITY);
207	switch (weight) {
208	default:
209		rtw89_warn(rtwdev, "unknown ent chan weight: %d\n", weight);
210		bitmap_zero(hal->entity_map, NUM_OF_RTW89_SUB_ENTITY);
211		fallthrough;
212	case 0:
213		rtw89_config_default_chandef(rtwdev);
214		fallthrough;
215	case 1:
216		last = RTW89_SUB_ENTITY_0;
217		mode = RTW89_ENTITY_MODE_SCC;
218		break;
219	case 2:
220		last = RTW89_SUB_ENTITY_1;
221		mode = rtw89_get_entity_mode(rtwdev);
222		if (mode == RTW89_ENTITY_MODE_MCC)
223			break;
224
225		mode = RTW89_ENTITY_MODE_MCC_PREPARE;
226		break;
227	}
228
229	for (idx = 0; idx <= last; idx++) {
230		chandef = rtw89_chandef_get(rtwdev, idx);
231		rtw89_get_channel_params(chandef, &chan);
232		if (chan.channel == 0) {
233			WARN(1, "Invalid channel on chanctx %d\n", idx);
234			return RTW89_ENTITY_MODE_INVALID;
235		}
236
237		rtw89_assign_entity_chan(rtwdev, idx, &chan);
238	}
239
240	rtw89_set_entity_mode(rtwdev, mode);
241	return mode;
242}
243
244static void rtw89_chanctx_notify(struct rtw89_dev *rtwdev,
245				 enum rtw89_chanctx_state state)
246{
247	const struct rtw89_chip_info *chip = rtwdev->chip;
248	const struct rtw89_chanctx_listener *listener = chip->chanctx_listener;
249	int i;
250
251	if (!listener)
252		return;
253
254	for (i = 0; i < NUM_OF_RTW89_CHANCTX_CALLBACKS; i++) {
255		if (!listener->callbacks[i])
256			continue;
257
258		rtw89_debug(rtwdev, RTW89_DBG_CHAN,
259			    "chanctx notify listener: cb %d, state %d\n",
260			    i, state);
261
262		listener->callbacks[i](rtwdev, state);
263	}
264}
265
266static int rtw89_mcc_start(struct rtw89_dev *rtwdev)
267{
268	if (rtwdev->scanning)
269		rtw89_hw_scan_abort(rtwdev, rtwdev->scan_info.scanning_vif);
270
271	rtw89_leave_lps(rtwdev);
272
273	rtw89_debug(rtwdev, RTW89_DBG_CHAN, "MCC start\n");
274	rtw89_chanctx_notify(rtwdev, RTW89_CHANCTX_STATE_MCC_START);
275	return 0;
276}
277
278static void rtw89_mcc_stop(struct rtw89_dev *rtwdev)
279{
280	rtw89_debug(rtwdev, RTW89_DBG_CHAN, "MCC stop\n");
281	rtw89_chanctx_notify(rtwdev, RTW89_CHANCTX_STATE_MCC_STOP);
282}
283
284void rtw89_chanctx_work(struct work_struct *work)
285{
286	struct rtw89_dev *rtwdev = container_of(work, struct rtw89_dev,
287						chanctx_work.work);
288	enum rtw89_entity_mode mode;
289	int ret;
290
291	mutex_lock(&rtwdev->mutex);
292
293	mode = rtw89_get_entity_mode(rtwdev);
294	switch (mode) {
295	case RTW89_ENTITY_MODE_MCC_PREPARE:
296		rtw89_set_entity_mode(rtwdev, RTW89_ENTITY_MODE_MCC);
297		rtw89_set_channel(rtwdev);
298
299		ret = rtw89_mcc_start(rtwdev);
300		if (ret)
301			rtw89_warn(rtwdev, "failed to start MCC: %d\n", ret);
302		break;
303	default:
304		break;
305	}
306
307	mutex_unlock(&rtwdev->mutex);
308}
309
310void rtw89_queue_chanctx_work(struct rtw89_dev *rtwdev)
311{
312	enum rtw89_entity_mode mode;
313	u32 delay;
314
315	mode = rtw89_get_entity_mode(rtwdev);
316	switch (mode) {
317	default:
318		return;
319	case RTW89_ENTITY_MODE_MCC_PREPARE:
320		delay = ieee80211_tu_to_usec(RTW89_CHANCTX_TIME_MCC_PREPARE);
321		break;
322	}
323
324	rtw89_debug(rtwdev, RTW89_DBG_CHAN,
325		    "queue chanctx work for mode %d with delay %d us\n",
326		    mode, delay);
327	ieee80211_queue_delayed_work(rtwdev->hw, &rtwdev->chanctx_work,
328				     usecs_to_jiffies(delay));
329}
330
331int rtw89_chanctx_ops_add(struct rtw89_dev *rtwdev,
332			  struct ieee80211_chanctx_conf *ctx)
333{
334	struct rtw89_hal *hal = &rtwdev->hal;
335	struct rtw89_chanctx_cfg *cfg = (struct rtw89_chanctx_cfg *)ctx->drv_priv;
336	const struct rtw89_chip_info *chip = rtwdev->chip;
337	u8 idx;
338
339	idx = find_first_zero_bit(hal->entity_map, NUM_OF_RTW89_SUB_ENTITY);
340	if (idx >= chip->support_chanctx_num)
341		return -ENOENT;
342
343	rtw89_config_entity_chandef(rtwdev, idx, &ctx->def);
344	rtw89_set_channel(rtwdev);
345	cfg->idx = idx;
346	hal->sub[idx].cfg = cfg;
347	return 0;
348}
349
350void rtw89_chanctx_ops_remove(struct rtw89_dev *rtwdev,
351			      struct ieee80211_chanctx_conf *ctx)
352{
353	struct rtw89_hal *hal = &rtwdev->hal;
354	struct rtw89_chanctx_cfg *cfg = (struct rtw89_chanctx_cfg *)ctx->drv_priv;
355	enum rtw89_entity_mode mode;
356	struct rtw89_vif *rtwvif;
357	u8 drop, roll;
358
359	drop = cfg->idx;
360	if (drop != RTW89_SUB_ENTITY_0)
361		goto out;
362
363	roll = find_next_bit(hal->entity_map, NUM_OF_RTW89_SUB_ENTITY, drop + 1);
364
365	/* Follow rtw89_config_default_chandef() when rtw89_entity_recalc(). */
366	if (roll == NUM_OF_RTW89_SUB_ENTITY)
367		goto out;
368
369	/* RTW89_SUB_ENTITY_0 is going to release, and another exists.
370	 * Make another roll down to RTW89_SUB_ENTITY_0 to replace.
371	 */
372	hal->sub[roll].cfg->idx = RTW89_SUB_ENTITY_0;
373	hal->sub[RTW89_SUB_ENTITY_0] = hal->sub[roll];
374
375	rtw89_for_each_rtwvif(rtwdev, rtwvif) {
376		if (rtwvif->sub_entity_idx == roll)
377			rtwvif->sub_entity_idx = RTW89_SUB_ENTITY_0;
378	}
379
380	atomic_cmpxchg(&hal->roc_entity_idx, roll, RTW89_SUB_ENTITY_0);
381
382	drop = roll;
383
384out:
385	mode = rtw89_get_entity_mode(rtwdev);
386	switch (mode) {
387	case RTW89_ENTITY_MODE_MCC:
388		rtw89_mcc_stop(rtwdev);
389		break;
390	default:
391		break;
392	}
393
394	clear_bit(drop, hal->entity_map);
395	rtw89_set_channel(rtwdev);
396}
397
398void rtw89_chanctx_ops_change(struct rtw89_dev *rtwdev,
399			      struct ieee80211_chanctx_conf *ctx,
400			      u32 changed)
401{
402	struct rtw89_chanctx_cfg *cfg = (struct rtw89_chanctx_cfg *)ctx->drv_priv;
403	u8 idx = cfg->idx;
404
405	if (changed & IEEE80211_CHANCTX_CHANGE_WIDTH) {
406		rtw89_config_entity_chandef(rtwdev, idx, &ctx->def);
407		rtw89_set_channel(rtwdev);
408	}
409}
410
411int rtw89_chanctx_ops_assign_vif(struct rtw89_dev *rtwdev,
412				 struct rtw89_vif *rtwvif,
413				 struct ieee80211_chanctx_conf *ctx)
414{
415	struct rtw89_chanctx_cfg *cfg = (struct rtw89_chanctx_cfg *)ctx->drv_priv;
416
417	rtwvif->sub_entity_idx = cfg->idx;
418	return 0;
419}
420
421void rtw89_chanctx_ops_unassign_vif(struct rtw89_dev *rtwdev,
422				    struct rtw89_vif *rtwvif,
423				    struct ieee80211_chanctx_conf *ctx)
424{
425	rtwvif->sub_entity_idx = RTW89_SUB_ENTITY_0;
426}
427