|
@@ -351,6 +351,80 @@ int cfg80211_chandef_dfs_required(struct wiphy *wiphy,
|
|
|
}
|
|
|
EXPORT_SYMBOL(cfg80211_chandef_dfs_required);
|
|
|
|
|
|
+static int cfg80211_get_chans_dfs_usable(struct wiphy *wiphy,
|
|
|
+ u32 center_freq,
|
|
|
+ u32 bandwidth)
|
|
|
+{
|
|
|
+ struct ieee80211_channel *c;
|
|
|
+ u32 freq, start_freq, end_freq;
|
|
|
+ int count = 0;
|
|
|
+
|
|
|
+ start_freq = cfg80211_get_start_freq(center_freq, bandwidth);
|
|
|
+ end_freq = cfg80211_get_end_freq(center_freq, bandwidth);
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Check entire range of channels for the bandwidth.
|
|
|
+ * Check all channels are DFS channels (DFS_USABLE or
|
|
|
+ * DFS_AVAILABLE). Return number of usable channels
|
|
|
+ * (require CAC). Allow DFS and non-DFS channel mix.
|
|
|
+ */
|
|
|
+ for (freq = start_freq; freq <= end_freq; freq += 20) {
|
|
|
+ c = ieee80211_get_channel(wiphy, freq);
|
|
|
+ if (!c)
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ if (c->flags & IEEE80211_CHAN_DISABLED)
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ if (c->flags & IEEE80211_CHAN_RADAR) {
|
|
|
+ if (c->dfs_state == NL80211_DFS_UNAVAILABLE)
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ if (c->dfs_state == NL80211_DFS_USABLE)
|
|
|
+ count++;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return count;
|
|
|
+}
|
|
|
+
|
|
|
+bool cfg80211_chandef_dfs_usable(struct wiphy *wiphy,
|
|
|
+ const struct cfg80211_chan_def *chandef)
|
|
|
+{
|
|
|
+ int width;
|
|
|
+ int r1, r2 = 0;
|
|
|
+
|
|
|
+ if (WARN_ON(!cfg80211_chandef_valid(chandef)))
|
|
|
+ return false;
|
|
|
+
|
|
|
+ width = cfg80211_chandef_get_width(chandef);
|
|
|
+ if (width < 0)
|
|
|
+ return false;
|
|
|
+
|
|
|
+ r1 = cfg80211_get_chans_dfs_usable(wiphy, chandef->center_freq1,
|
|
|
+ width);
|
|
|
+
|
|
|
+ if (r1 < 0)
|
|
|
+ return false;
|
|
|
+
|
|
|
+ switch (chandef->width) {
|
|
|
+ case NL80211_CHAN_WIDTH_80P80:
|
|
|
+ WARN_ON(!chandef->center_freq2);
|
|
|
+ r2 = cfg80211_get_chans_dfs_usable(wiphy,
|
|
|
+ chandef->center_freq2,
|
|
|
+ width);
|
|
|
+ if (r2 < 0)
|
|
|
+ return false;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ WARN_ON(chandef->center_freq2);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ return (r1 + r2 > 0);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
static bool cfg80211_secondary_chans_ok(struct wiphy *wiphy,
|
|
|
u32 center_freq, u32 bandwidth,
|
|
|
u32 prohibited_flags)
|