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
rtw89_get_subband_type(enum rtw89_band band,u8 center_chan)8 static enum rtw89_subband rtw89_get_subband_type(enum rtw89_band band,
9 u8 center_chan)
10 {
11 switch (band) {
12 default:
13 case RTW89_BAND_2G:
14 switch (center_chan) {
15 default:
16 case 1 ... 14:
17 return RTW89_CH_2G;
18 }
19 case RTW89_BAND_5G:
20 switch (center_chan) {
21 default:
22 case 36 ... 64:
23 return RTW89_CH_5G_BAND_1;
24 case 100 ... 144:
25 return RTW89_CH_5G_BAND_3;
26 case 149 ... 177:
27 return RTW89_CH_5G_BAND_4;
28 }
29 case RTW89_BAND_6G:
30 switch (center_chan) {
31 default:
32 case 1 ... 29:
33 return RTW89_CH_6G_BAND_IDX0;
34 case 33 ... 61:
35 return RTW89_CH_6G_BAND_IDX1;
36 case 65 ... 93:
37 return RTW89_CH_6G_BAND_IDX2;
38 case 97 ... 125:
39 return RTW89_CH_6G_BAND_IDX3;
40 case 129 ... 157:
41 return RTW89_CH_6G_BAND_IDX4;
42 case 161 ... 189:
43 return RTW89_CH_6G_BAND_IDX5;
44 case 193 ... 221:
45 return RTW89_CH_6G_BAND_IDX6;
46 case 225 ... 253:
47 return RTW89_CH_6G_BAND_IDX7;
48 }
49 }
50 }
51
rtw89_get_primary_chan_idx(enum rtw89_bandwidth bw,u32 center_freq,u32 primary_freq)52 static enum rtw89_sc_offset rtw89_get_primary_chan_idx(enum rtw89_bandwidth bw,
53 u32 center_freq,
54 u32 primary_freq)
55 {
56 u8 primary_chan_idx;
57 u32 offset;
58
59 switch (bw) {
60 default:
61 case RTW89_CHANNEL_WIDTH_20:
62 primary_chan_idx = RTW89_SC_DONT_CARE;
63 break;
64 case RTW89_CHANNEL_WIDTH_40:
65 if (primary_freq > center_freq)
66 primary_chan_idx = RTW89_SC_20_UPPER;
67 else
68 primary_chan_idx = RTW89_SC_20_LOWER;
69 break;
70 case RTW89_CHANNEL_WIDTH_80:
71 case RTW89_CHANNEL_WIDTH_160:
72 if (primary_freq > center_freq) {
73 offset = (primary_freq - center_freq - 10) / 20;
74 primary_chan_idx = RTW89_SC_20_UPPER + offset * 2;
75 } else {
76 offset = (center_freq - primary_freq - 10) / 20;
77 primary_chan_idx = RTW89_SC_20_LOWER + offset * 2;
78 }
79 break;
80 }
81
82 return primary_chan_idx;
83 }
84
rtw89_chan_create(struct rtw89_chan * chan,u8 center_chan,u8 primary_chan,enum rtw89_band band,enum rtw89_bandwidth bandwidth)85 void rtw89_chan_create(struct rtw89_chan *chan, u8 center_chan, u8 primary_chan,
86 enum rtw89_band band, enum rtw89_bandwidth bandwidth)
87 {
88 enum nl80211_band nl_band = rtw89_hw_to_nl80211_band(band);
89 u32 center_freq, primary_freq;
90
91 memset(chan, 0, sizeof(*chan));
92 chan->channel = center_chan;
93 chan->primary_channel = primary_chan;
94 chan->band_type = band;
95 chan->band_width = bandwidth;
96
97 center_freq = ieee80211_channel_to_frequency(center_chan, nl_band);
98 primary_freq = ieee80211_channel_to_frequency(primary_chan, nl_band);
99
100 chan->freq = center_freq;
101 chan->subband_type = rtw89_get_subband_type(band, center_chan);
102 chan->pri_ch_idx = rtw89_get_primary_chan_idx(bandwidth, center_freq,
103 primary_freq);
104 }
105
rtw89_assign_entity_chan(struct rtw89_dev * rtwdev,enum rtw89_sub_entity_idx idx,const struct rtw89_chan * new)106 bool rtw89_assign_entity_chan(struct rtw89_dev *rtwdev,
107 enum rtw89_sub_entity_idx idx,
108 const struct rtw89_chan *new)
109 {
110 struct rtw89_hal *hal = &rtwdev->hal;
111 struct rtw89_chan *chan = &hal->chan[idx];
112 struct rtw89_chan_rcd *rcd = &hal->chan_rcd[idx];
113 bool band_changed;
114
115 rcd->prev_primary_channel = chan->primary_channel;
116 rcd->prev_band_type = chan->band_type;
117 band_changed = new->band_type != chan->band_type;
118
119 *chan = *new;
120 return band_changed;
121 }
122
__rtw89_config_entity_chandef(struct rtw89_dev * rtwdev,enum rtw89_sub_entity_idx idx,const struct cfg80211_chan_def * chandef,bool from_stack)123 static void __rtw89_config_entity_chandef(struct rtw89_dev *rtwdev,
124 enum rtw89_sub_entity_idx idx,
125 const struct cfg80211_chan_def *chandef,
126 bool from_stack)
127 {
128 struct rtw89_hal *hal = &rtwdev->hal;
129
130 hal->chandef[idx] = *chandef;
131
132 if (from_stack)
133 set_bit(idx, hal->entity_map);
134 }
135
rtw89_config_entity_chandef(struct rtw89_dev * rtwdev,enum rtw89_sub_entity_idx idx,const struct cfg80211_chan_def * chandef)136 void rtw89_config_entity_chandef(struct rtw89_dev *rtwdev,
137 enum rtw89_sub_entity_idx idx,
138 const struct cfg80211_chan_def *chandef)
139 {
140 __rtw89_config_entity_chandef(rtwdev, idx, chandef, true);
141 }
142
rtw89_config_default_chandef(struct rtw89_dev * rtwdev)143 static void rtw89_config_default_chandef(struct rtw89_dev *rtwdev)
144 {
145 struct cfg80211_chan_def chandef = {0};
146
147 rtw89_get_default_chandef(&chandef);
148 __rtw89_config_entity_chandef(rtwdev, RTW89_SUB_ENTITY_0, &chandef, false);
149 }
150
rtw89_entity_init(struct rtw89_dev * rtwdev)151 void rtw89_entity_init(struct rtw89_dev *rtwdev)
152 {
153 struct rtw89_hal *hal = &rtwdev->hal;
154
155 bitmap_zero(hal->entity_map, NUM_OF_RTW89_SUB_ENTITY);
156 rtw89_config_default_chandef(rtwdev);
157 }
158
rtw89_entity_recalc(struct rtw89_dev * rtwdev)159 enum rtw89_entity_mode rtw89_entity_recalc(struct rtw89_dev *rtwdev)
160 {
161 struct rtw89_hal *hal = &rtwdev->hal;
162 enum rtw89_entity_mode mode;
163 u8 weight;
164
165 weight = bitmap_weight(hal->entity_map, NUM_OF_RTW89_SUB_ENTITY);
166 switch (weight) {
167 default:
168 rtw89_warn(rtwdev, "unknown ent chan weight: %d\n", weight);
169 bitmap_zero(hal->entity_map, NUM_OF_RTW89_SUB_ENTITY);
170 fallthrough;
171 case 0:
172 rtw89_config_default_chandef(rtwdev);
173 fallthrough;
174 case 1:
175 mode = RTW89_ENTITY_MODE_SCC;
176 break;
177 }
178
179 rtw89_set_entity_mode(rtwdev, mode);
180 return mode;
181 }
182
rtw89_chanctx_ops_add(struct rtw89_dev * rtwdev,struct ieee80211_chanctx_conf * ctx)183 int rtw89_chanctx_ops_add(struct rtw89_dev *rtwdev,
184 struct ieee80211_chanctx_conf *ctx)
185 {
186 struct rtw89_hal *hal = &rtwdev->hal;
187 struct rtw89_chanctx_cfg *cfg = (struct rtw89_chanctx_cfg *)ctx->drv_priv;
188 const struct rtw89_chip_info *chip = rtwdev->chip;
189 u8 idx;
190
191 idx = find_first_zero_bit(hal->entity_map, NUM_OF_RTW89_SUB_ENTITY);
192 if (idx >= chip->support_chanctx_num)
193 return -ENOENT;
194
195 rtw89_config_entity_chandef(rtwdev, idx, &ctx->def);
196 rtw89_set_channel(rtwdev);
197 cfg->idx = idx;
198 return 0;
199 }
200
rtw89_chanctx_ops_remove(struct rtw89_dev * rtwdev,struct ieee80211_chanctx_conf * ctx)201 void rtw89_chanctx_ops_remove(struct rtw89_dev *rtwdev,
202 struct ieee80211_chanctx_conf *ctx)
203 {
204 struct rtw89_hal *hal = &rtwdev->hal;
205 struct rtw89_chanctx_cfg *cfg = (struct rtw89_chanctx_cfg *)ctx->drv_priv;
206
207 clear_bit(cfg->idx, hal->entity_map);
208 rtw89_set_channel(rtwdev);
209 }
210
rtw89_chanctx_ops_change(struct rtw89_dev * rtwdev,struct ieee80211_chanctx_conf * ctx,u32 changed)211 void rtw89_chanctx_ops_change(struct rtw89_dev *rtwdev,
212 struct ieee80211_chanctx_conf *ctx,
213 u32 changed)
214 {
215 struct rtw89_chanctx_cfg *cfg = (struct rtw89_chanctx_cfg *)ctx->drv_priv;
216 u8 idx = cfg->idx;
217
218 if (changed & IEEE80211_CHANCTX_CHANGE_WIDTH) {
219 rtw89_config_entity_chandef(rtwdev, idx, &ctx->def);
220 rtw89_set_channel(rtwdev);
221 }
222 }
223
rtw89_chanctx_ops_assign_vif(struct rtw89_dev * rtwdev,struct rtw89_vif * rtwvif,struct ieee80211_chanctx_conf * ctx)224 int rtw89_chanctx_ops_assign_vif(struct rtw89_dev *rtwdev,
225 struct rtw89_vif *rtwvif,
226 struct ieee80211_chanctx_conf *ctx)
227 {
228 return 0;
229 }
230
rtw89_chanctx_ops_unassign_vif(struct rtw89_dev * rtwdev,struct rtw89_vif * rtwvif,struct ieee80211_chanctx_conf * ctx)231 void rtw89_chanctx_ops_unassign_vif(struct rtw89_dev *rtwdev,
232 struct rtw89_vif *rtwvif,
233 struct ieee80211_chanctx_conf *ctx)
234 {
235 }
236