Message ID | 1434020791-16291-2-git-send-email-matthias.may@neratec.com (mailing list archive) |
---|---|
State | Changes Requested |
Headers | show |
On Thu, 2015-06-11 at 13:06 +0200, Matthias May wrote: > 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. You can't make a patch like this that breaks the compile - all these need to be a single patch. That said, you could get away with not changing the public freq_reg_info() API since the callers thereof don't need it, you could make a __freq_reg_info() that has the bandwidth and freq_reg_info() that doesn't. johannes -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Thu, 2015-06-11 at 13:06 +0200, Matthias May wrote: > 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; This makes no sense to me. You have the same code below, but why would you care? You can just look at the reg_rule's max_bandwidth, no? johannes -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On 11/06/15 13:44, Johannes Berg wrote: > On Thu, 2015-06-11 at 13:06 +0200, Matthias May wrote: > >> 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; > This makes no sense to me. > > You have the same code below, but why would you care? You can just look > at the reg_rule's max_bandwidth, no? > > johannes > Using the dummy country code: country XS: DFS-UNSET (5170 - 5180 @ 5), (N/A, 14), (N/A) (5175 - 5185 @ 10), (N/A, 17), (N/A) (5170 - 5190 @ 20), (N/A, 20), (N/A) For a center freq of 5175 The first loop finds the first rule. --> we want this. The second loop doesn't find anything. The third loop doesn't find anything. However for a center freq of 5180 The first loop find the first rule The second loop find the second rule The third loop find the third rule. --> We want this If there are different overlapping rules for the different bandwidths different results can be returned, especially at the border of a frequency range. A work colleague pointed out that it could be done more efficiently: const struct ieee80211_regdomain *regd; const struct ieee80211_reg_rule *reg_rule = NULL; u32 bw; regd = reg_get_regdomain(wiphy); for (bw = MHZ_TO_KHZ(20); bw >= min_bw; bw = bw / 2) { reg_rule = freq_reg_info_regd(wiphy, center_freq, bw, regd); if (!IS_ERR(reg_rule)) return reg_rule; } return reg_rule; However after some more discussion we noticed, that this again would allow to start 20MHz wide operation at the border This is because when setting the flags we only look at the max_bandwidth of the returned rule. I guess we would have to recheck if a certain width fits a center freq when setting this flags. Will have to think a bit more how to solve this without having to recheck everything again... Matthias -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On Thu, 2015-06-11 at 14:46 +0200, Matthias May wrote: > Using the dummy country code: > country XS: DFS-UNSET > (5170 - 5180 @ 5), (N/A, 14), (N/A) > (5175 - 5185 @ 10), (N/A, 17), (N/A) > (5170 - 5190 @ 20), (N/A, 20), (N/A) > > For a center freq of 5175 > The first loop finds the first rule. --> we want this. > The second loop doesn't find anything. > The third loop doesn't find anything. > > However for a center freq of 5180 > The first loop find the first rule > The second loop find the second rule > The third loop find the third rule. --> We want this > > If there are different overlapping rules for the different bandwidths > different results can be returned, especially at the border of a > frequency range. Hmmm. Can we just forbid those overlapping rules, and say you want AUTO-BW? I mean, do you see a reason for this otherwise? johannes -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
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))
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.may@neratec.com> --- include/net/cfg80211.h | 3 ++- net/wireless/reg.c | 46 +++++++++++++++++++++++++++++++++++++--------- 2 files changed, 39 insertions(+), 10 deletions(-)