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
rtw89_get_subband_type(enum rtw89_band band,u8 center_chan)11 static 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
rtw89_get_primary_chan_idx(enum rtw89_bandwidth bw,u32 center_freq,u32 primary_freq)55 static 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
rtw89_chan_create(struct rtw89_chan * chan,u8 center_chan,u8 primary_chan,enum rtw89_band band,enum rtw89_bandwidth bandwidth)88 void 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
rtw89_assign_entity_chan(struct rtw89_dev * rtwdev,enum rtw89_sub_entity_idx idx,const struct rtw89_chan * new)109 bool 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
__rtw89_config_entity_chandef(struct rtw89_dev * rtwdev,enum rtw89_sub_entity_idx idx,const struct cfg80211_chan_def * chandef,bool from_stack)127 static 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
rtw89_config_entity_chandef(struct rtw89_dev * rtwdev,enum rtw89_sub_entity_idx idx,const struct cfg80211_chan_def * chandef)140 void 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
rtw89_config_roc_chandef(struct rtw89_dev * rtwdev,enum rtw89_sub_entity_idx idx,const struct cfg80211_chan_def * chandef)147 void 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
rtw89_config_default_chandef(struct rtw89_dev * rtwdev)179 static 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
rtw89_entity_init(struct rtw89_dev * rtwdev)187 void 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
rtw89_entity_recalc(struct rtw89_dev * rtwdev)196 enum 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
rtw89_chanctx_notify(struct rtw89_dev * rtwdev,enum rtw89_chanctx_state state)244 static 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
rtw89_mcc_start(struct rtw89_dev * rtwdev)266 static 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
rtw89_mcc_stop(struct rtw89_dev * rtwdev)278 static 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
rtw89_chanctx_work(struct work_struct * work)284 void 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
rtw89_queue_chanctx_work(struct rtw89_dev * rtwdev)310 void 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
rtw89_chanctx_ops_add(struct rtw89_dev * rtwdev,struct ieee80211_chanctx_conf * ctx)331 int 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
rtw89_chanctx_ops_remove(struct rtw89_dev * rtwdev,struct ieee80211_chanctx_conf * ctx)350 void 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
384 out:
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
rtw89_chanctx_ops_change(struct rtw89_dev * rtwdev,struct ieee80211_chanctx_conf * ctx,u32 changed)398 void 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
rtw89_chanctx_ops_assign_vif(struct rtw89_dev * rtwdev,struct rtw89_vif * rtwvif,struct ieee80211_chanctx_conf * ctx)411 int 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
rtw89_chanctx_ops_unassign_vif(struct rtw89_dev * rtwdev,struct rtw89_vif * rtwvif,struct ieee80211_chanctx_conf * ctx)421 void 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