This patch changes the API of freq_freq_info() to take as additional argument
the minimum bandwidth the caller can handle.
If multiple rules match, the match with the widest bandwidth is returned.

Signed-off-by: Matthias May <matthias....@neratec.com>
---
 include/net/cfg80211.h |  3 ++-
 net/wireless/reg.c     | 46 +++++++++++++++++++++++++++++++++++++---------
 2 files changed, 39 insertions(+), 10 deletions(-)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index a741678..ac5d8e8 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -3876,6 +3876,7 @@ void wiphy_apply_custom_regulatory(struct wiphy *wiphy,
  * freq_reg_info - get regulatory information for the given frequency
  * @wiphy: the wiphy for which we want to process this rule for
  * @center_freq: Frequency in KHz for which we want regulatory information for
+ * @min_bw: The minimum bandwidth in KHz the caller can handle
  *
  * Use this function to get the regulatory rule for a specific frequency on
  * a given wireless device. If the device has a specific regulatory domain
@@ -3891,7 +3892,7 @@ void wiphy_apply_custom_regulatory(struct wiphy *wiphy,
  * purely subjective and right now it's 802.11 specific.
  */
 const struct ieee80211_reg_rule *freq_reg_info(struct wiphy *wiphy,
-                                              u32 center_freq);
+                                              u32 center_freq, u32 min_bw);
 
 /**
  * reg_initiator_name - map regulatory request initiator enum to name
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index d359e06..c4f85bb 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -1003,7 +1003,7 @@ static u32 map_regdom_flags(u32 rd_flags)
 }
 
 static const struct ieee80211_reg_rule *
-freq_reg_info_regd(struct wiphy *wiphy, u32 center_freq,
+freq_reg_info_regd(struct wiphy *wiphy, u32 center_freq, u32 bw,
                   const struct ieee80211_regdomain *regd)
 {
        int i;
@@ -1028,7 +1028,7 @@ freq_reg_info_regd(struct wiphy *wiphy, u32 center_freq,
                if (!band_rule_found)
                        band_rule_found = freq_in_rule_band(fr, center_freq);
 
-               bw_fits = reg_does_bw_fit(fr, center_freq, MHZ_TO_KHZ(20));
+               bw_fits = reg_does_bw_fit(fr, center_freq, bw);
 
                if (band_rule_found && bw_fits)
                        return rr;
@@ -1041,13 +1041,22 @@ freq_reg_info_regd(struct wiphy *wiphy, u32 center_freq,
 }
 
 const struct ieee80211_reg_rule *freq_reg_info(struct wiphy *wiphy,
-                                              u32 center_freq)
+                                              u32 center_freq, u32 min_bw)
 {
        const struct ieee80211_regdomain *regd;
+       const struct ieee80211_reg_rule *rr_tmp = NULL;
+       const struct ieee80211_reg_rule *reg_rule = NULL;
+       u32 bw;
 
        regd = reg_get_regdomain(wiphy);
 
-       return freq_reg_info_regd(wiphy, center_freq, regd);
+       for(bw=min_bw; bw <= MHZ_TO_KHZ(20); bw=bw*2) {
+               rr_tmp = freq_reg_info_regd(wiphy, center_freq, bw, regd);
+               if(!reg_rule || !IS_ERR(rr_tmp))
+                       reg_rule = rr_tmp;
+       }
+
+       return reg_rule;
 }
 EXPORT_SYMBOL(freq_reg_info);
 
@@ -1134,7 +1143,8 @@ static void handle_channel(struct wiphy *wiphy,
 
        flags = chan->orig_flags;
 
-       reg_rule = freq_reg_info(wiphy, MHZ_TO_KHZ(chan->center_freq));
+       reg_rule = freq_reg_info(wiphy, MHZ_TO_KHZ(chan->center_freq),
+                                MHZ_TO_KHZ(20));
        if (IS_ERR(reg_rule)) {
                /*
                 * We will disable all channels that do not match our
@@ -1176,8 +1186,12 @@ static void handle_channel(struct wiphy *wiphy,
        if (reg_rule->flags & NL80211_RRF_AUTO_BW)
                max_bandwidth_khz = reg_get_max_bandwidth(regd, reg_rule);
 
+       if (max_bandwidth_khz < MHZ_TO_KHZ(10))
+               bw_flags = IEEE80211_CHAN_NO_10MHZ;
+       if (max_bandwidth_khz < MHZ_TO_KHZ(20))
+               bw_flags |= IEEE80211_CHAN_NO_20MHZ;
        if (max_bandwidth_khz < MHZ_TO_KHZ(40))
-               bw_flags = IEEE80211_CHAN_NO_HT40;
+               bw_flags |= IEEE80211_CHAN_NO_HT40;
        if (max_bandwidth_khz < MHZ_TO_KHZ(80))
                bw_flags |= IEEE80211_CHAN_NO_80MHZ;
        if (max_bandwidth_khz < MHZ_TO_KHZ(160))
@@ -1692,12 +1706,22 @@ static void handle_channel_custom(struct wiphy *wiphy,
 {
        u32 bw_flags = 0;
        const struct ieee80211_reg_rule *reg_rule = NULL;
+       const struct ieee80211_reg_rule *rr_tmp = NULL;
        const struct ieee80211_power_rule *power_rule = NULL;
        const struct ieee80211_freq_range *freq_range = NULL;
        u32 max_bandwidth_khz;
+       u32 bw;
 
-       reg_rule = freq_reg_info_regd(wiphy, MHZ_TO_KHZ(chan->center_freq),
-                                     regd);
+       /* Check if a frequency fits a rule for 5, 10 and 20MHz in that order.
+        * Use the rule with the widest bandwidth that fits.
+        */
+       for(bw=MHZ_TO_KHZ(5); bw <= MHZ_TO_KHZ(20); bw=bw*2) {
+               rr_tmp = freq_reg_info_regd(wiphy,
+                                           MHZ_TO_KHZ(chan->center_freq), bw,
+                                           regd);
+               if(!reg_rule || !IS_ERR(rr_tmp))
+                       reg_rule = rr_tmp;
+       }
 
        if (IS_ERR(reg_rule)) {
                REG_DBG_PRINT("Disabling freq %d MHz as custom regd has no rule 
that fits it\n",
@@ -1721,8 +1745,12 @@ static void handle_channel_custom(struct wiphy *wiphy,
        if (reg_rule->flags & NL80211_RRF_AUTO_BW)
                max_bandwidth_khz = reg_get_max_bandwidth(regd, reg_rule);
 
+       if (max_bandwidth_khz < MHZ_TO_KHZ(10))
+               bw_flags = IEEE80211_CHAN_NO_10MHZ;
+       if (max_bandwidth_khz < MHZ_TO_KHZ(20))
+               bw_flags |= IEEE80211_CHAN_NO_20MHZ;
        if (max_bandwidth_khz < MHZ_TO_KHZ(40))
-               bw_flags = IEEE80211_CHAN_NO_HT40;
+               bw_flags |= IEEE80211_CHAN_NO_HT40;
        if (max_bandwidth_khz < MHZ_TO_KHZ(80))
                bw_flags |= IEEE80211_CHAN_NO_80MHZ;
        if (max_bandwidth_khz < MHZ_TO_KHZ(160))
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to