cfg80211: allow restricting supported dfs regions
authorFelix Fietkau <nbd@openwrt.org>
Mon, 5 May 2014 09:48:40 +0000 (11:48 +0200)
committerJohannes Berg <johannes.berg@intel.com>
Tue, 13 May 2014 13:50:06 +0000 (15:50 +0200)
At the moment, the ath9k/ath10k DFS module only supports detecting ETSI
radar patterns.
Add a bitmap in the interface combinations, indicating which DFS regions
are supported by the detector. If unset, support for all regions is
assumed.

Signed-off-by: Felix Fietkau <nbd@openwrt.org>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
include/net/cfg80211.h
include/uapi/linux/nl80211.h
net/wireless/nl80211.c
net/wireless/util.c

index 5c7169b0ac5780f9a86b266c46bc903629d558e0..e3a48b0a2b3bf80bd11556960294d6a8a2e579c3 100644 (file)
@@ -2638,6 +2638,7 @@ struct ieee80211_iface_limit {
  *     between infrastructure and AP types must match. This is required
  *     only in special cases.
  * @radar_detect_widths: bitmap of channel widths supported for radar detection
+ * @radar_detect_regions: bitmap of regions supported for radar detection
  *
  * With this structure the driver can describe which interface
  * combinations it supports concurrently.
@@ -2695,6 +2696,7 @@ struct ieee80211_iface_combination {
        u8 n_limits;
        bool beacon_int_infra_match;
        u8 radar_detect_widths;
+       u8 radar_detect_regions;
 };
 
 struct ieee80211_txrx_stypes {
index 406010d4def049d3880b49a0b4362e75b93c47c1..b65095a85dee0254ef67e786eb714683648fadad 100644 (file)
@@ -3688,6 +3688,8 @@ enum nl80211_iface_limit_attrs {
  *     different channels may be used within this group.
  * @NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS: u32 attribute containing the bitmap
  *     of supported channel widths for radar detection.
+ * @NL80211_IFACE_COMB_RADAR_DETECT_REGIONS: u32 attribute containing the bitmap
+ *     of supported regulatory regions for radar detection.
  * @NUM_NL80211_IFACE_COMB: number of attributes
  * @MAX_NL80211_IFACE_COMB: highest attribute number
  *
@@ -3721,6 +3723,7 @@ enum nl80211_if_combination_attrs {
        NL80211_IFACE_COMB_STA_AP_BI_MATCH,
        NL80211_IFACE_COMB_NUM_CHANNELS,
        NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS,
+       NL80211_IFACE_COMB_RADAR_DETECT_REGIONS,
 
        /* keep last */
        NUM_NL80211_IFACE_COMB,
index 0f1b18f209d6254800ac50f28b4d454017fe7e62..c0833830cfe73424da9f74782d077ef110a3e35c 100644 (file)
@@ -970,8 +970,10 @@ static int nl80211_put_iface_combinations(struct wiphy *wiphy,
                                c->max_interfaces))
                        goto nla_put_failure;
                if (large &&
-                   nla_put_u32(msg, NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS,
-                               c->radar_detect_widths))
+                   (nla_put_u32(msg, NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS,
+                               c->radar_detect_widths) ||
+                    nla_put_u32(msg, NL80211_IFACE_COMB_RADAR_DETECT_REGIONS,
+                               c->radar_detect_regions)))
                        goto nla_put_failure;
 
                nla_nest_end(msg, nl_combi);
index a756429b3a0a0f1738818ef7b2abe67435d21032..8c61d5c6fad3a658c9ed5a3b17854c7780e4c30b 100644 (file)
@@ -1274,10 +1274,20 @@ int cfg80211_iter_combinations(struct wiphy *wiphy,
                                            void *data),
                               void *data)
 {
+       const struct ieee80211_regdomain *regdom;
+       enum nl80211_dfs_regions region = 0;
        int i, j, iftype;
        int num_interfaces = 0;
        u32 used_iftypes = 0;
 
+       if (radar_detect) {
+               rcu_read_lock();
+               regdom = rcu_dereference(cfg80211_regdomain);
+               if (regdom)
+                       region = regdom->dfs_region;
+               rcu_read_unlock();
+       }
+
        for (iftype = 0; iftype < NUM_NL80211_IFTYPES; iftype++) {
                num_interfaces += iftype_num[iftype];
                if (iftype_num[iftype] > 0 &&
@@ -1318,6 +1328,10 @@ int cfg80211_iter_combinations(struct wiphy *wiphy,
                if (radar_detect != (c->radar_detect_widths & radar_detect))
                        goto cont;
 
+               if (radar_detect && c->radar_detect_regions &&
+                   !(c->radar_detect_regions & BIT(region)))
+                       goto cont;
+
                /* Finally check that all iftypes that we're currently
                 * using are actually part of this combination. If they
                 * aren't then we can't use this combination and have