Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec...
[cascardo/linux.git] / net / wireless / reg.c
index b725a31..32d8310 100644 (file)
@@ -573,8 +573,9 @@ static const struct ieee80211_regdomain *reg_get_regdomain(struct wiphy *wiphy)
        return get_cfg80211_regdom();
 }
 
-unsigned int reg_get_max_bandwidth(const struct ieee80211_regdomain *rd,
-                                  const struct ieee80211_reg_rule *rule)
+static unsigned int
+reg_get_max_bandwidth_from_range(const struct ieee80211_regdomain *rd,
+                                const struct ieee80211_reg_rule *rule)
 {
        const struct ieee80211_freq_range *freq_range = &rule->freq_range;
        const struct ieee80211_freq_range *freq_range_tmp;
@@ -622,6 +623,27 @@ unsigned int reg_get_max_bandwidth(const struct ieee80211_regdomain *rd,
        return end_freq - start_freq;
 }
 
+unsigned int reg_get_max_bandwidth(const struct ieee80211_regdomain *rd,
+                                  const struct ieee80211_reg_rule *rule)
+{
+       unsigned int bw = reg_get_max_bandwidth_from_range(rd, rule);
+
+       if (rule->flags & NL80211_RRF_NO_160MHZ)
+               bw = min_t(unsigned int, bw, MHZ_TO_KHZ(80));
+       if (rule->flags & NL80211_RRF_NO_80MHZ)
+               bw = min_t(unsigned int, bw, MHZ_TO_KHZ(40));
+
+       /*
+        * HT40+/HT40- limits are handled per-channel. Only limit BW if both
+        * are not allowed.
+        */
+       if (rule->flags & NL80211_RRF_NO_HT40MINUS &&
+           rule->flags & NL80211_RRF_NO_HT40PLUS)
+               bw = min_t(unsigned int, bw, MHZ_TO_KHZ(20));
+
+       return bw;
+}
+
 /* Sanity check on a regulatory rule */
 static bool is_valid_reg_rule(const struct ieee80211_reg_rule *rule)
 {
@@ -946,6 +968,16 @@ static u32 map_regdom_flags(u32 rd_flags)
                channel_flags |= IEEE80211_CHAN_NO_OFDM;
        if (rd_flags & NL80211_RRF_NO_OUTDOOR)
                channel_flags |= IEEE80211_CHAN_INDOOR_ONLY;
+       if (rd_flags & NL80211_RRF_GO_CONCURRENT)
+               channel_flags |= IEEE80211_CHAN_GO_CONCURRENT;
+       if (rd_flags & NL80211_RRF_NO_HT40MINUS)
+               channel_flags |= IEEE80211_CHAN_NO_HT40MINUS;
+       if (rd_flags & NL80211_RRF_NO_HT40PLUS)
+               channel_flags |= IEEE80211_CHAN_NO_HT40PLUS;
+       if (rd_flags & NL80211_RRF_NO_80MHZ)
+               channel_flags |= IEEE80211_CHAN_NO_80MHZ;
+       if (rd_flags & NL80211_RRF_NO_160MHZ)
+               channel_flags |= IEEE80211_CHAN_NO_160MHZ;
        return channel_flags;
 }
 
@@ -1565,10 +1597,23 @@ static void handle_channel_custom(struct wiphy *wiphy,
        if (max_bandwidth_khz < MHZ_TO_KHZ(160))
                bw_flags |= IEEE80211_CHAN_NO_160MHZ;
 
+       chan->dfs_state_entered = jiffies;
+       chan->dfs_state = NL80211_DFS_USABLE;
+
+       chan->beacon_found = false;
        chan->flags |= map_regdom_flags(reg_rule->flags) | bw_flags;
        chan->max_antenna_gain = (int) MBI_TO_DBI(power_rule->max_antenna_gain);
        chan->max_reg_power = chan->max_power =
                (int) MBM_TO_DBM(power_rule->max_eirp);
+
+       if (chan->flags & IEEE80211_CHAN_RADAR) {
+               if (reg_rule->dfs_cac_ms)
+                       chan->dfs_cac_ms = reg_rule->dfs_cac_ms;
+               else
+                       chan->dfs_cac_ms = IEEE80211_DFS_MIN_CAC_TIME_MS;
+       }
+
+       chan->max_power = chan->max_reg_power;
 }
 
 static void handle_band_custom(struct wiphy *wiphy,