|
@@ -1004,7 +1004,7 @@ static u32 map_regdom_flags(u32 rd_flags)
|
|
|
|
|
|
static const struct ieee80211_reg_rule *
|
|
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,
|
|
- const struct ieee80211_regdomain *regd)
|
|
|
|
|
|
+ const struct ieee80211_regdomain *regd, u32 bw)
|
|
{
|
|
{
|
|
int i;
|
|
int i;
|
|
bool band_rule_found = false;
|
|
bool band_rule_found = false;
|
|
@@ -1028,7 +1028,7 @@ freq_reg_info_regd(struct wiphy *wiphy, u32 center_freq,
|
|
if (!band_rule_found)
|
|
if (!band_rule_found)
|
|
band_rule_found = freq_in_rule_band(fr, center_freq);
|
|
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)
|
|
if (band_rule_found && bw_fits)
|
|
return rr;
|
|
return rr;
|
|
@@ -1040,14 +1040,26 @@ freq_reg_info_regd(struct wiphy *wiphy, u32 center_freq,
|
|
return ERR_PTR(-EINVAL);
|
|
return ERR_PTR(-EINVAL);
|
|
}
|
|
}
|
|
|
|
|
|
-const struct ieee80211_reg_rule *freq_reg_info(struct wiphy *wiphy,
|
|
|
|
- u32 center_freq)
|
|
|
|
|
|
+const struct ieee80211_reg_rule *__freq_reg_info(struct wiphy *wiphy,
|
|
|
|
+ u32 center_freq, u32 min_bw)
|
|
{
|
|
{
|
|
- const struct ieee80211_regdomain *regd;
|
|
|
|
|
|
+ const struct ieee80211_regdomain *regd = reg_get_regdomain(wiphy);
|
|
|
|
+ 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, regd, bw);
|
|
|
|
+ if (!IS_ERR(reg_rule))
|
|
|
|
+ return reg_rule;
|
|
|
|
+ }
|
|
|
|
|
|
- return freq_reg_info_regd(wiphy, center_freq, regd);
|
|
|
|
|
|
+ return reg_rule;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+const struct ieee80211_reg_rule *freq_reg_info(struct wiphy *wiphy,
|
|
|
|
+ u32 center_freq)
|
|
|
|
+{
|
|
|
|
+ return __freq_reg_info(wiphy, center_freq, MHZ_TO_KHZ(20));
|
|
}
|
|
}
|
|
EXPORT_SYMBOL(freq_reg_info);
|
|
EXPORT_SYMBOL(freq_reg_info);
|
|
|
|
|
|
@@ -1176,8 +1188,20 @@ static void handle_channel(struct wiphy *wiphy,
|
|
if (reg_rule->flags & NL80211_RRF_AUTO_BW)
|
|
if (reg_rule->flags & NL80211_RRF_AUTO_BW)
|
|
max_bandwidth_khz = reg_get_max_bandwidth(regd, reg_rule);
|
|
max_bandwidth_khz = reg_get_max_bandwidth(regd, reg_rule);
|
|
|
|
|
|
|
|
+ /* If we get a reg_rule we can assume that at least 5Mhz fit */
|
|
|
|
+ if (!reg_does_bw_fit(freq_range, MHZ_TO_KHZ(chan->center_freq),
|
|
|
|
+ MHZ_TO_KHZ(10)))
|
|
|
|
+ bw_flags |= IEEE80211_CHAN_NO_10MHZ;
|
|
|
|
+ if (!reg_does_bw_fit(freq_range, MHZ_TO_KHZ(chan->center_freq),
|
|
|
|
+ MHZ_TO_KHZ(20)))
|
|
|
|
+ bw_flags |= IEEE80211_CHAN_NO_20MHZ;
|
|
|
|
+
|
|
|
|
+ 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))
|
|
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))
|
|
if (max_bandwidth_khz < MHZ_TO_KHZ(80))
|
|
bw_flags |= IEEE80211_CHAN_NO_80MHZ;
|
|
bw_flags |= IEEE80211_CHAN_NO_80MHZ;
|
|
if (max_bandwidth_khz < MHZ_TO_KHZ(160))
|
|
if (max_bandwidth_khz < MHZ_TO_KHZ(160))
|
|
@@ -1695,9 +1719,15 @@ static void handle_channel_custom(struct wiphy *wiphy,
|
|
const struct ieee80211_power_rule *power_rule = NULL;
|
|
const struct ieee80211_power_rule *power_rule = NULL;
|
|
const struct ieee80211_freq_range *freq_range = NULL;
|
|
const struct ieee80211_freq_range *freq_range = NULL;
|
|
u32 max_bandwidth_khz;
|
|
u32 max_bandwidth_khz;
|
|
|
|
+ u32 bw;
|
|
|
|
|
|
- reg_rule = freq_reg_info_regd(wiphy, MHZ_TO_KHZ(chan->center_freq),
|
|
|
|
- regd);
|
|
|
|
|
|
+ for (bw = MHZ_TO_KHZ(20); bw >= MHZ_TO_KHZ(5); bw = bw / 2) {
|
|
|
|
+ reg_rule = freq_reg_info_regd(wiphy,
|
|
|
|
+ MHZ_TO_KHZ(chan->center_freq),
|
|
|
|
+ regd, bw);
|
|
|
|
+ if (!IS_ERR(reg_rule))
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
|
|
if (IS_ERR(reg_rule)) {
|
|
if (IS_ERR(reg_rule)) {
|
|
REG_DBG_PRINT("Disabling freq %d MHz as custom regd has no rule that fits it\n",
|
|
REG_DBG_PRINT("Disabling freq %d MHz as custom regd has no rule that fits it\n",
|
|
@@ -1721,8 +1751,20 @@ static void handle_channel_custom(struct wiphy *wiphy,
|
|
if (reg_rule->flags & NL80211_RRF_AUTO_BW)
|
|
if (reg_rule->flags & NL80211_RRF_AUTO_BW)
|
|
max_bandwidth_khz = reg_get_max_bandwidth(regd, reg_rule);
|
|
max_bandwidth_khz = reg_get_max_bandwidth(regd, reg_rule);
|
|
|
|
|
|
|
|
+ /* If we get a reg_rule we can assume that at least 5Mhz fit */
|
|
|
|
+ if (!reg_does_bw_fit(freq_range, MHZ_TO_KHZ(chan->center_freq),
|
|
|
|
+ MHZ_TO_KHZ(10)))
|
|
|
|
+ bw_flags |= IEEE80211_CHAN_NO_10MHZ;
|
|
|
|
+ if (!reg_does_bw_fit(freq_range, MHZ_TO_KHZ(chan->center_freq),
|
|
|
|
+ MHZ_TO_KHZ(20)))
|
|
|
|
+ bw_flags |= IEEE80211_CHAN_NO_20MHZ;
|
|
|
|
+
|
|
|
|
+ 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))
|
|
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))
|
|
if (max_bandwidth_khz < MHZ_TO_KHZ(80))
|
|
bw_flags |= IEEE80211_CHAN_NO_80MHZ;
|
|
bw_flags |= IEEE80211_CHAN_NO_80MHZ;
|
|
if (max_bandwidth_khz < MHZ_TO_KHZ(160))
|
|
if (max_bandwidth_khz < MHZ_TO_KHZ(160))
|