diff options
author | Johannes Berg <johannes.berg@intel.com> | 2012-11-22 10:59:45 -0500 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2012-11-27 03:18:25 -0500 |
commit | 9f5e8f6efc7c2601136b27d9c7325c245f8fd19a (patch) | |
tree | 99e89e550d6687240364659e78ff4276bd12aae2 /net/wireless/chan.c | |
parent | ec816087e8978b74c1bd5fae0e335dd97d964e9f (diff) |
cfg80211: rework chandef checking and export it
Some of the chandef checking that we do in cfg80211
to check if a channel is supported or not is also
needed in mac80211, so rework that a bit and export
the functions that are needed.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/wireless/chan.c')
-rw-r--r-- | net/wireless/chan.c | 92 |
1 files changed, 63 insertions, 29 deletions
diff --git a/net/wireless/chan.c b/net/wireless/chan.c index bf2dfd54ff3b..b5f69831e318 100644 --- a/net/wireless/chan.c +++ b/net/wireless/chan.c | |||
@@ -44,7 +44,7 @@ void cfg80211_chandef_create(struct cfg80211_chan_def *chandef, | |||
44 | } | 44 | } |
45 | EXPORT_SYMBOL(cfg80211_chandef_create); | 45 | EXPORT_SYMBOL(cfg80211_chandef_create); |
46 | 46 | ||
47 | bool cfg80211_chan_def_valid(const struct cfg80211_chan_def *chandef) | 47 | bool cfg80211_chandef_valid(const struct cfg80211_chan_def *chandef) |
48 | { | 48 | { |
49 | u32 control_freq; | 49 | u32 control_freq; |
50 | 50 | ||
@@ -105,6 +105,7 @@ bool cfg80211_chan_def_valid(const struct cfg80211_chan_def *chandef) | |||
105 | 105 | ||
106 | return true; | 106 | return true; |
107 | } | 107 | } |
108 | EXPORT_SYMBOL(cfg80211_chandef_valid); | ||
108 | 109 | ||
109 | static void chandef_primary_freqs(const struct cfg80211_chan_def *c, | 110 | static void chandef_primary_freqs(const struct cfg80211_chan_def *c, |
110 | int *pri40, int *pri80) | 111 | int *pri40, int *pri80) |
@@ -187,9 +188,9 @@ cfg80211_chandef_compatible(const struct cfg80211_chan_def *c1, | |||
187 | } | 188 | } |
188 | EXPORT_SYMBOL(cfg80211_chandef_compatible); | 189 | EXPORT_SYMBOL(cfg80211_chandef_compatible); |
189 | 190 | ||
190 | bool cfg80211_secondary_chans_ok(struct wiphy *wiphy, | 191 | static bool cfg80211_secondary_chans_ok(struct wiphy *wiphy, |
191 | u32 center_freq, u32 bandwidth, | 192 | u32 center_freq, u32 bandwidth, |
192 | u32 prohibited_flags) | 193 | u32 prohibited_flags) |
193 | { | 194 | { |
194 | struct ieee80211_channel *c; | 195 | struct ieee80211_channel *c; |
195 | u32 freq; | 196 | u32 freq; |
@@ -205,55 +206,88 @@ bool cfg80211_secondary_chans_ok(struct wiphy *wiphy, | |||
205 | return true; | 206 | return true; |
206 | } | 207 | } |
207 | 208 | ||
208 | static bool cfg80211_check_beacon_chans(struct wiphy *wiphy, | 209 | bool cfg80211_chandef_usable(struct wiphy *wiphy, |
209 | u32 center_freq, u32 bw) | 210 | const struct cfg80211_chan_def *chandef, |
211 | u32 prohibited_flags) | ||
210 | { | 212 | { |
211 | return cfg80211_secondary_chans_ok(wiphy, center_freq, bw, | 213 | struct ieee80211_sta_ht_cap *ht_cap; |
212 | IEEE80211_CHAN_DISABLED | | 214 | struct ieee80211_sta_vht_cap *vht_cap; |
213 | IEEE80211_CHAN_PASSIVE_SCAN | | 215 | u32 width, control_freq; |
214 | IEEE80211_CHAN_NO_IBSS | | ||
215 | IEEE80211_CHAN_RADAR); | ||
216 | } | ||
217 | 216 | ||
218 | bool cfg80211_reg_can_beacon(struct wiphy *wiphy, | 217 | if (WARN_ON(!cfg80211_chandef_valid(chandef))) |
219 | struct cfg80211_chan_def *chandef) | 218 | return false; |
220 | { | ||
221 | u32 width; | ||
222 | bool res; | ||
223 | 219 | ||
224 | trace_cfg80211_reg_can_beacon(wiphy, chandef); | 220 | ht_cap = &wiphy->bands[chandef->chan->band]->ht_cap; |
221 | vht_cap = &wiphy->bands[chandef->chan->band]->vht_cap; | ||
225 | 222 | ||
226 | if (WARN_ON(!cfg80211_chan_def_valid(chandef))) { | 223 | control_freq = chandef->chan->center_freq; |
227 | trace_cfg80211_return_bool(false); | ||
228 | return false; | ||
229 | } | ||
230 | 224 | ||
231 | switch (chandef->width) { | 225 | switch (chandef->width) { |
232 | case NL80211_CHAN_WIDTH_20_NOHT: | ||
233 | case NL80211_CHAN_WIDTH_20: | 226 | case NL80211_CHAN_WIDTH_20: |
227 | if (!ht_cap->ht_supported) | ||
228 | return false; | ||
229 | case NL80211_CHAN_WIDTH_20_NOHT: | ||
234 | width = 20; | 230 | width = 20; |
235 | break; | 231 | break; |
236 | case NL80211_CHAN_WIDTH_40: | 232 | case NL80211_CHAN_WIDTH_40: |
237 | width = 40; | 233 | width = 40; |
234 | if (!ht_cap->ht_supported) | ||
235 | return false; | ||
236 | if (!(ht_cap->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) || | ||
237 | ht_cap->cap & IEEE80211_HT_CAP_40MHZ_INTOLERANT) | ||
238 | return false; | ||
239 | if (chandef->center_freq1 < control_freq && | ||
240 | chandef->chan->flags & IEEE80211_CHAN_NO_HT40MINUS) | ||
241 | return false; | ||
242 | if (chandef->center_freq1 > control_freq && | ||
243 | chandef->chan->flags & IEEE80211_CHAN_NO_HT40PLUS) | ||
244 | return false; | ||
238 | break; | 245 | break; |
239 | case NL80211_CHAN_WIDTH_80: | ||
240 | case NL80211_CHAN_WIDTH_80P80: | 246 | case NL80211_CHAN_WIDTH_80P80: |
247 | if (!(vht_cap->cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ)) | ||
248 | return false; | ||
249 | case NL80211_CHAN_WIDTH_80: | ||
250 | if (!vht_cap->vht_supported) | ||
251 | return false; | ||
241 | width = 80; | 252 | width = 80; |
242 | break; | 253 | break; |
243 | case NL80211_CHAN_WIDTH_160: | 254 | case NL80211_CHAN_WIDTH_160: |
255 | if (!vht_cap->vht_supported) | ||
256 | return false; | ||
257 | if (!(vht_cap->cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ)) | ||
258 | return false; | ||
244 | width = 160; | 259 | width = 160; |
245 | break; | 260 | break; |
246 | default: | 261 | default: |
247 | WARN_ON_ONCE(1); | 262 | WARN_ON_ONCE(1); |
248 | trace_cfg80211_return_bool(false); | ||
249 | return false; | 263 | return false; |
250 | } | 264 | } |
251 | 265 | ||
252 | res = cfg80211_check_beacon_chans(wiphy, chandef->center_freq1, width); | 266 | /* TODO: missing regulatory check on 80/160 bandwidth */ |
267 | |||
268 | if (!cfg80211_secondary_chans_ok(wiphy, chandef->center_freq1, | ||
269 | width, prohibited_flags)) | ||
270 | return false; | ||
271 | |||
272 | if (!chandef->center_freq2) | ||
273 | return true; | ||
274 | return cfg80211_secondary_chans_ok(wiphy, chandef->center_freq2, | ||
275 | width, prohibited_flags); | ||
276 | } | ||
277 | EXPORT_SYMBOL(cfg80211_chandef_usable); | ||
278 | |||
279 | bool cfg80211_reg_can_beacon(struct wiphy *wiphy, | ||
280 | struct cfg80211_chan_def *chandef) | ||
281 | { | ||
282 | bool res; | ||
283 | |||
284 | trace_cfg80211_reg_can_beacon(wiphy, chandef); | ||
253 | 285 | ||
254 | if (res && chandef->center_freq2) | 286 | res = cfg80211_chandef_usable(wiphy, chandef, |
255 | res = cfg80211_check_beacon_chans(wiphy, chandef->center_freq2, | 287 | IEEE80211_CHAN_DISABLED | |
256 | width); | 288 | IEEE80211_CHAN_PASSIVE_SCAN | |
289 | IEEE80211_CHAN_NO_IBSS | | ||
290 | IEEE80211_CHAN_RADAR); | ||
257 | 291 | ||
258 | trace_cfg80211_return_bool(res); | 292 | trace_cfg80211_return_bool(res); |
259 | return res; | 293 | return res; |