* [PATCH 0/5] cfg80211: HT bandwidth checks
@ 2009-05-02 4:37 Luis R. Rodriguez
2009-05-02 4:37 ` [PATCH 1/5] cfg80211: Process regulatory max bandwidth checks for HT40 Luis R. Rodriguez
` (4 more replies)
0 siblings, 5 replies; 8+ messages in thread
From: Luis R. Rodriguez @ 2009-05-02 4:37 UTC (permalink / raw)
To: linville, johannes; +Cc: linux-wireless, Luis R. Rodriguez
This is a respin of the HT40 bandwidth patches with the
fixes pointed out by Jouni. This time I leave out the debugfs
stuff for another series which will follow up.
Luis R. Rodriguez (5):
cfg80211: Process regulatory max bandwidth checks for HT40
wireless: rename IEEE80211_CHAN_NO_FAT_* to HT40-/+
mac80211: check if HT40+/- is allowed before sending assoc
cfg80211: check allowed channel type upon userspace requests
mac80211/cfg80211: move wiphy specific debugfs entries to cfg80211
drivers/net/wireless/ath/regd.c | 10 +-
drivers/net/wireless/iwlwifi/iwl-core.c | 4 +-
drivers/net/wireless/iwlwifi/iwl-eeprom.c | 8 +-
include/net/cfg80211.h | 22 ++-
net/mac80211/debugfs.c | 16 ---
net/mac80211/ieee80211_i.h | 4 -
net/mac80211/mlme.c | 12 +-
net/wireless/Kconfig | 8 +
net/wireless/Makefile | 1 +
net/wireless/core.c | 5 +
net/wireless/core.h | 11 ++
net/wireless/debugfs.c | 70 ++++++++++
net/wireless/debugfs.h | 14 ++
net/wireless/nl80211.c | 39 +++---
net/wireless/reg.c | 201 +++++++++++++++++++++++------
15 files changed, 319 insertions(+), 106 deletions(-)
create mode 100644 net/wireless/debugfs.c
create mode 100644 net/wireless/debugfs.h
^ permalink raw reply [flat|nested] 8+ messages in thread* [PATCH 1/5] cfg80211: Process regulatory max bandwidth checks for HT40 2009-05-02 4:37 [PATCH 0/5] cfg80211: HT bandwidth checks Luis R. Rodriguez @ 2009-05-02 4:37 ` Luis R. Rodriguez 2009-05-02 4:37 ` [PATCH 2/5] wireless: rename IEEE80211_CHAN_NO_FAT_* to HT40-/+ Luis R. Rodriguez ` (3 subsequent siblings) 4 siblings, 0 replies; 8+ messages in thread From: Luis R. Rodriguez @ 2009-05-02 4:37 UTC (permalink / raw) To: linville, johannes; +Cc: linux-wireless, Luis R. Rodriguez We are not correctly listening to the regulatory max bandwidth settings. To actually make use of it we need to redesign things a bit. This patch does the work for that. We do this to so we can obey to regulatory rules accordingly for use of HT40. We end up dealing with HT40 by having two passes for each channel. The first check will see if a 20 MHz channel fits into the channel's center freq on a given frequency range. We check for a 20 MHz banwidth channel as that is the maximum an individual channel will use, at least for now. The first pass will go ahead and check if the regulatory rule for that given center of frequency allows 40 MHz bandwidths and we use this to determine whether or not the channel supports HT40 or not. So to support HT40 you'll need at a regulatory rule that allows you to use 40 MHz channels but you're channel must also be enabled and support 20 MHz by itself. The second pass is done after we do the regulatory checks over an device's supported channel list. On each channel we'll check if the control channel and the extension both: o exist o are enabled o regulatory allows 40 MHz bandwidth on its frequency range This work allows allows us to idependently check for HT40- and HT40+. Signed-off-by: Luis R. Rodriguez <lrodriguez@atheros.com> --- drivers/net/wireless/ath/regd.c | 10 +- include/net/cfg80211.h | 14 ++- net/wireless/reg.c | 201 +++++++++++++++++++++++++++++++-------- 3 files changed, 175 insertions(+), 50 deletions(-) diff --git a/drivers/net/wireless/ath/regd.c b/drivers/net/wireless/ath/regd.c index fdf07c8..7a89f9f 100644 --- a/drivers/net/wireless/ath/regd.c +++ b/drivers/net/wireless/ath/regd.c @@ -200,8 +200,10 @@ ath_reg_apply_beaconing_flags(struct wiphy *wiphy, continue; if (initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) { - r = freq_reg_info(wiphy, ch->center_freq, - &bandwidth, ®_rule); + r = freq_reg_info(wiphy, + ch->center_freq, + bandwidth, + ®_rule); if (r) continue; /* @@ -265,7 +267,7 @@ ath_reg_apply_active_scan_flags(struct wiphy *wiphy, */ ch = &sband->channels[11]; /* CH 12 */ - r = freq_reg_info(wiphy, ch->center_freq, &bandwidth, ®_rule); + r = freq_reg_info(wiphy, ch->center_freq, bandwidth, ®_rule); if (!r) { if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN)) if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN) @@ -273,7 +275,7 @@ ath_reg_apply_active_scan_flags(struct wiphy *wiphy, } ch = &sband->channels[12]; /* CH 13 */ - r = freq_reg_info(wiphy, ch->center_freq, &bandwidth, ®_rule); + r = freq_reg_info(wiphy, ch->center_freq, bandwidth, ®_rule); if (!r) { if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN)) if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index b8a7676..40647e4 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -70,6 +70,9 @@ enum ieee80211_channel_flags { IEEE80211_CHAN_NO_FAT_BELOW = 1<<5, }; +#define IEEE80211_CHAN_NO_HT40 \ + (IEEE80211_CHAN_NO_FAT_ABOVE | IEEE80211_CHAN_NO_FAT_BELOW) + /** * struct ieee80211_channel - channel definition * @@ -1311,9 +1314,10 @@ extern void wiphy_apply_custom_regulatory( * 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 - * @bandwidth: the bandwidth requirement you have in KHz, if you do not have one - * you can set this to 0. If this frequency is allowed we then set - * this value to the maximum allowed bandwidth. + * @desired_bw_khz: the desired max bandwidth you want to use per + * channel. Note that this is still 20 MHz if you want to use HT40 + * as HT40 makes use of two channels for its 40 MHz width bandwidth. + * If set to 0 we'll assume you want the standard 20 MHz. * @reg_rule: the regulatory rule which we have for this frequency * * Use this function to get the regulatory rule for a specific frequency on @@ -1328,7 +1332,9 @@ extern void wiphy_apply_custom_regulatory( * freq_in_rule_band() for our current definition of a band -- this is purely * subjective and right now its 802.11 specific. */ -extern int freq_reg_info(struct wiphy *wiphy, u32 center_freq, u32 *bandwidth, +extern int freq_reg_info(struct wiphy *wiphy, + u32 center_freq, + u32 desired_bw_khz, const struct ieee80211_reg_rule **reg_rule); /* diff --git a/net/wireless/reg.c b/net/wireless/reg.c index d68950d..a0a1614 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -48,12 +48,6 @@ static struct regulatory_request *last_request; /* To trigger userspace events */ static struct platform_device *reg_pdev; -/* Keep the ordering from large to small */ -static u32 supported_bandwidths[] = { - MHZ_TO_KHZ(40), - MHZ_TO_KHZ(20), -}; - /* * Central wireless core regulatory domains, we only need two, * the current one and a world regulatory domain in case we have no @@ -435,19 +429,20 @@ static bool is_valid_rd(const struct ieee80211_regdomain *rd) return true; } -/* Returns value in KHz */ -static u32 freq_max_bandwidth(const struct ieee80211_freq_range *freq_range, - u32 freq) +static bool reg_does_bw_fit(const struct ieee80211_freq_range *freq_range, + u32 center_freq_khz, + u32 bw_khz) { - unsigned int i; - for (i = 0; i < ARRAY_SIZE(supported_bandwidths); i++) { - u32 start_freq_khz = freq - supported_bandwidths[i]/2; - u32 end_freq_khz = freq + supported_bandwidths[i]/2; - if (start_freq_khz >= freq_range->start_freq_khz && - end_freq_khz <= freq_range->end_freq_khz) - return supported_bandwidths[i]; - } - return 0; + u32 start_freq_khz, end_freq_khz; + + start_freq_khz = center_freq_khz - (bw_khz/2); + end_freq_khz = center_freq_khz + (bw_khz/2); + + if (start_freq_khz >= freq_range->start_freq_khz && + end_freq_khz <= freq_range->end_freq_khz) + return true; + + return false; } /** @@ -847,14 +842,17 @@ static u32 map_regdom_flags(u32 rd_flags) static int freq_reg_info_regd(struct wiphy *wiphy, u32 center_freq, - u32 *bandwidth, + u32 desired_bw_khz, const struct ieee80211_reg_rule **reg_rule, const struct ieee80211_regdomain *custom_regd) { int i; bool band_rule_found = false; const struct ieee80211_regdomain *regd; - u32 max_bandwidth = 0; + bool bw_fits = false; + + if (!desired_bw_khz) + desired_bw_khz = MHZ_TO_KHZ(20); regd = custom_regd ? custom_regd : cfg80211_regdomain; @@ -887,38 +885,54 @@ static int freq_reg_info_regd(struct wiphy *wiphy, if (!band_rule_found) band_rule_found = freq_in_rule_band(fr, center_freq); - max_bandwidth = freq_max_bandwidth(fr, center_freq); + bw_fits = reg_does_bw_fit(fr, + center_freq, + desired_bw_khz); - if (max_bandwidth && *bandwidth <= max_bandwidth) { + if (band_rule_found && bw_fits) { *reg_rule = rr; - *bandwidth = max_bandwidth; - break; + return 0; } } if (!band_rule_found) return -ERANGE; - return !max_bandwidth; + return -EINVAL; } EXPORT_SYMBOL(freq_reg_info); -int freq_reg_info(struct wiphy *wiphy, u32 center_freq, u32 *bandwidth, - const struct ieee80211_reg_rule **reg_rule) +int freq_reg_info(struct wiphy *wiphy, + u32 center_freq, + u32 desired_bw_khz, + const struct ieee80211_reg_rule **reg_rule) { assert_cfg80211_lock(); - return freq_reg_info_regd(wiphy, center_freq, - bandwidth, reg_rule, NULL); + return freq_reg_info_regd(wiphy, + center_freq, + desired_bw_khz, + reg_rule, + NULL); } +/* + * Note that right now we assume the desired channel bandwidth + * is always 20 MHz for each individual channel (HT40 uses 20 MHz + * per channel, the primary and the extension channel). To support + * smaller custom bandwidths such as 5 MHz or 10 MHz we'll need a + * new ieee80211_channel.target_bw and re run the regulatory check + * on the wiphy with the target_bw specified. Then we can simply use + * that below for the desired_bw_khz below. + */ static void handle_channel(struct wiphy *wiphy, enum ieee80211_band band, unsigned int chan_idx) { int r; - u32 flags; - u32 max_bandwidth = 0; + u32 flags, bw_flags = 0; + u32 desired_bw_khz = MHZ_TO_KHZ(20); const struct ieee80211_reg_rule *reg_rule = NULL; const struct ieee80211_power_rule *power_rule = NULL; + const struct ieee80211_freq_range *freq_range = NULL; struct ieee80211_supported_band *sband; struct ieee80211_channel *chan; struct wiphy *request_wiphy = NULL; @@ -933,8 +947,10 @@ static void handle_channel(struct wiphy *wiphy, enum ieee80211_band band, flags = chan->orig_flags; - r = freq_reg_info(wiphy, MHZ_TO_KHZ(chan->center_freq), - &max_bandwidth, ®_rule); + r = freq_reg_info(wiphy, + MHZ_TO_KHZ(chan->center_freq), + desired_bw_khz, + ®_rule); if (r) { /* @@ -977,6 +993,10 @@ static void handle_channel(struct wiphy *wiphy, enum ieee80211_band band, } power_rule = ®_rule->power_rule; + freq_range = ®_rule->freq_range; + + if (freq_range->max_bandwidth_khz < MHZ_TO_KHZ(40)) + bw_flags = IEEE80211_CHAN_NO_HT40; if (last_request->initiator == NL80211_REGDOM_SET_BY_DRIVER && request_wiphy && request_wiphy == wiphy && @@ -987,19 +1007,19 @@ static void handle_channel(struct wiphy *wiphy, enum ieee80211_band band, * settings */ chan->flags = chan->orig_flags = - map_regdom_flags(reg_rule->flags); + map_regdom_flags(reg_rule->flags) | bw_flags; chan->max_antenna_gain = chan->orig_mag = (int) MBI_TO_DBI(power_rule->max_antenna_gain); - chan->max_bandwidth = KHZ_TO_MHZ(max_bandwidth); + chan->max_bandwidth = KHZ_TO_MHZ(desired_bw_khz); chan->max_power = chan->orig_mpwr = (int) MBM_TO_DBM(power_rule->max_eirp); return; } - chan->flags = flags | map_regdom_flags(reg_rule->flags); + chan->flags = flags | bw_flags | map_regdom_flags(reg_rule->flags); chan->max_antenna_gain = min(chan->orig_mag, (int) MBI_TO_DBI(power_rule->max_antenna_gain)); - chan->max_bandwidth = KHZ_TO_MHZ(max_bandwidth); + chan->max_bandwidth = KHZ_TO_MHZ(desired_bw_khz); if (chan->orig_mpwr) chan->max_power = min(chan->orig_mpwr, (int) MBM_TO_DBM(power_rule->max_eirp)); @@ -1156,6 +1176,93 @@ static void reg_process_beacons(struct wiphy *wiphy) wiphy_update_beacon_reg(wiphy); } +static bool is_ht40_not_allowed(struct ieee80211_channel *chan) +{ + if (!chan) + return true; + if (chan->flags & IEEE80211_CHAN_DISABLED) + return true; + /* This would happen when regulatory rules disallow HT40 completely */ + if (IEEE80211_CHAN_NO_HT40 == (chan->flags & (IEEE80211_CHAN_NO_HT40))) + return true; + return false; +} + +static void reg_process_ht_flags_channel(struct wiphy *wiphy, + enum ieee80211_band band, + unsigned int chan_idx) +{ + struct ieee80211_supported_band *sband; + struct ieee80211_channel *channel; + struct ieee80211_channel *channel_before = NULL, *channel_after = NULL; + unsigned int i; + + assert_cfg80211_lock(); + + sband = wiphy->bands[band]; + BUG_ON(chan_idx >= sband->n_channels); + channel = &sband->channels[chan_idx]; + + if (is_ht40_not_allowed(channel)) { + channel->flags |= IEEE80211_CHAN_NO_HT40; + return; + } + + /* + * We need to ensure the extension channels exist to + * be able to use HT40- or HT40+, this finds them (or not) + */ + for (i = 0; i < sband->n_channels; i++) { + struct ieee80211_channel *c = &sband->channels[i]; + if (c->center_freq == (channel->center_freq - 20)) + channel_before = c; + if (c->center_freq == (channel->center_freq + 20)) + channel_after = c; + } + + /* + * Please note that this assumes target bandwidth is 20 MHz, + * if that ever changes we also need to change the below logic + * to include that as well. + */ + if (is_ht40_not_allowed(channel_before)) + channel->flags |= IEEE80211_CHAN_NO_FAT_BELOW; + else + channel->flags &= ~IEEE80211_CHAN_NO_FAT_BELOW; + + if (is_ht40_not_allowed(channel_after)) + channel->flags |= IEEE80211_CHAN_NO_FAT_ABOVE; + else + channel->flags &= ~IEEE80211_CHAN_NO_FAT_ABOVE; +} + +static void reg_process_ht_flags_band(struct wiphy *wiphy, + enum ieee80211_band band) +{ + unsigned int i; + struct ieee80211_supported_band *sband; + + BUG_ON(!wiphy->bands[band]); + sband = wiphy->bands[band]; + + for (i = 0; i < sband->n_channels; i++) + reg_process_ht_flags_channel(wiphy, band, i); +} + +static void reg_process_ht_flags(struct wiphy *wiphy) +{ + enum ieee80211_band band; + + if (!wiphy) + return; + + for (band = 0; band < IEEE80211_NUM_BANDS; band++) { + if (wiphy->bands[band]) + reg_process_ht_flags_band(wiphy, band); + } + +} + void wiphy_update_regulatory(struct wiphy *wiphy, enum nl80211_reg_initiator initiator) { @@ -1169,6 +1276,7 @@ void wiphy_update_regulatory(struct wiphy *wiphy, } out: reg_process_beacons(wiphy); + reg_process_ht_flags(wiphy); if (wiphy->reg_notifier) wiphy->reg_notifier(wiphy, last_request); } @@ -1179,9 +1287,11 @@ static void handle_channel_custom(struct wiphy *wiphy, const struct ieee80211_regdomain *regd) { int r; - u32 max_bandwidth = 0; + u32 desired_bw_khz = MHZ_TO_KHZ(20); + u32 bw_flags = 0; const struct ieee80211_reg_rule *reg_rule = NULL; const struct ieee80211_power_rule *power_rule = NULL; + const struct ieee80211_freq_range *freq_range = NULL; struct ieee80211_supported_band *sband; struct ieee80211_channel *chan; @@ -1191,8 +1301,11 @@ static void handle_channel_custom(struct wiphy *wiphy, BUG_ON(chan_idx >= sband->n_channels); chan = &sband->channels[chan_idx]; - r = freq_reg_info_regd(wiphy, MHZ_TO_KHZ(chan->center_freq), - &max_bandwidth, ®_rule, regd); + r = freq_reg_info_regd(wiphy, + MHZ_TO_KHZ(chan->center_freq), + desired_bw_khz, + ®_rule, + regd); if (r) { chan->flags = IEEE80211_CHAN_DISABLED; @@ -1200,10 +1313,14 @@ static void handle_channel_custom(struct wiphy *wiphy, } power_rule = ®_rule->power_rule; + freq_range = ®_rule->freq_range; + + if (freq_range->max_bandwidth_khz < MHZ_TO_KHZ(40)) + bw_flags = IEEE80211_CHAN_NO_HT40; - chan->flags |= map_regdom_flags(reg_rule->flags); + 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_bandwidth = KHZ_TO_MHZ(max_bandwidth); + chan->max_bandwidth = KHZ_TO_MHZ(desired_bw_khz); chan->max_power = (int) MBM_TO_DBM(power_rule->max_eirp); } -- 1.6.0.6 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 2/5] wireless: rename IEEE80211_CHAN_NO_FAT_* to HT40-/+ 2009-05-02 4:37 [PATCH 0/5] cfg80211: HT bandwidth checks Luis R. Rodriguez 2009-05-02 4:37 ` [PATCH 1/5] cfg80211: Process regulatory max bandwidth checks for HT40 Luis R. Rodriguez @ 2009-05-02 4:37 ` Luis R. Rodriguez 2009-05-02 4:37 ` [PATCH 3/5] mac80211: check if HT40+/- is allowed before sending assoc Luis R. Rodriguez ` (2 subsequent siblings) 4 siblings, 0 replies; 8+ messages in thread From: Luis R. Rodriguez @ 2009-05-02 4:37 UTC (permalink / raw) To: linville, johannes; +Cc: linux-wireless, Luis R. Rodriguez This is more consistent with our nl80211 naming convention for HT40-/+. Signed-off-by: Luis R. Rodriguez <lrodriguez@atheros.com> --- drivers/net/wireless/iwlwifi/iwl-core.c | 4 ++-- drivers/net/wireless/iwlwifi/iwl-eeprom.c | 8 ++++---- include/net/cfg80211.h | 10 +++++----- net/mac80211/mlme.c | 4 ++-- net/wireless/reg.c | 8 ++++---- 5 files changed, 17 insertions(+), 17 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 0f21fc1..c68449f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -591,10 +591,10 @@ static u8 iwl_is_channel_extension(struct iwl_priv *priv, if (extension_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_ABOVE) return !(ch_info->fat_extension_channel & - IEEE80211_CHAN_NO_FAT_ABOVE); + IEEE80211_CHAN_NO_HT40PLUS); else if (extension_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_BELOW) return !(ch_info->fat_extension_channel & - IEEE80211_CHAN_NO_FAT_BELOW); + IEEE80211_CHAN_NO_HT40MINUS); return 0; } diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c index 75517d0..9d73f19 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c @@ -481,8 +481,8 @@ int iwl_init_channel_map(struct iwl_priv *priv) /* First write that fat is not enabled, and then enable * one by one */ ch_info->fat_extension_channel = - (IEEE80211_CHAN_NO_FAT_ABOVE | - IEEE80211_CHAN_NO_FAT_BELOW); + (IEEE80211_CHAN_NO_HT40PLUS | + IEEE80211_CHAN_NO_HT40MINUS); if (!(is_channel_valid(ch_info))) { IWL_DEBUG_INFO(priv, "Ch. %d Flags %x [%sGHz] - " @@ -561,7 +561,7 @@ int iwl_init_channel_map(struct iwl_priv *priv) fat_extension_chan = 0; else fat_extension_chan = - IEEE80211_CHAN_NO_FAT_BELOW; + IEEE80211_CHAN_NO_HT40MINUS; /* Set up driver's info for lower half */ iwl_set_fat_chan_info(priv, ieeeband, @@ -573,7 +573,7 @@ int iwl_init_channel_map(struct iwl_priv *priv) iwl_set_fat_chan_info(priv, ieeeband, (eeprom_ch_index[ch] + 4), &(eeprom_ch_info[ch]), - IEEE80211_CHAN_NO_FAT_ABOVE); + IEEE80211_CHAN_NO_HT40PLUS); } } diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 40647e4..73394e4 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -56,9 +56,9 @@ enum ieee80211_band { * on this channel. * @IEEE80211_CHAN_NO_IBSS: IBSS is not allowed on this channel. * @IEEE80211_CHAN_RADAR: Radar detection is required on this channel. - * @IEEE80211_CHAN_NO_FAT_ABOVE: extension channel above this channel + * @IEEE80211_CHAN_NO_HT40PLUS: extension channel above this channel * is not permitted. - * @IEEE80211_CHAN_NO_FAT_BELOW: extension channel below this channel + * @IEEE80211_CHAN_NO_HT40MINUS: extension channel below this channel * is not permitted. */ enum ieee80211_channel_flags { @@ -66,12 +66,12 @@ enum ieee80211_channel_flags { IEEE80211_CHAN_PASSIVE_SCAN = 1<<1, IEEE80211_CHAN_NO_IBSS = 1<<2, IEEE80211_CHAN_RADAR = 1<<3, - IEEE80211_CHAN_NO_FAT_ABOVE = 1<<4, - IEEE80211_CHAN_NO_FAT_BELOW = 1<<5, + IEEE80211_CHAN_NO_HT40PLUS = 1<<4, + IEEE80211_CHAN_NO_HT40MINUS = 1<<5, }; #define IEEE80211_CHAN_NO_HT40 \ - (IEEE80211_CHAN_NO_FAT_ABOVE | IEEE80211_CHAN_NO_FAT_BELOW) + (IEEE80211_CHAN_NO_HT40PLUS | IEEE80211_CHAN_NO_HT40MINUS) /** * struct ieee80211_channel - channel definition diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 5509c5a..02f93fa 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -349,13 +349,13 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) switch (ht_info->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: - if (flags & IEEE80211_CHAN_NO_FAT_ABOVE) { + if (flags & IEEE80211_CHAN_NO_HT40PLUS) { cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; cap &= ~IEEE80211_HT_CAP_SGI_40; } break; case IEEE80211_HT_PARAM_CHA_SEC_BELOW: - if (flags & IEEE80211_CHAN_NO_FAT_BELOW) { + if (flags & IEEE80211_CHAN_NO_HT40MINUS) { cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; cap &= ~IEEE80211_HT_CAP_SGI_40; } diff --git a/net/wireless/reg.c b/net/wireless/reg.c index a0a1614..9bb16d3 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -1226,14 +1226,14 @@ static void reg_process_ht_flags_channel(struct wiphy *wiphy, * to include that as well. */ if (is_ht40_not_allowed(channel_before)) - channel->flags |= IEEE80211_CHAN_NO_FAT_BELOW; + channel->flags |= IEEE80211_CHAN_NO_HT40MINUS; else - channel->flags &= ~IEEE80211_CHAN_NO_FAT_BELOW; + channel->flags &= ~IEEE80211_CHAN_NO_HT40MINUS; if (is_ht40_not_allowed(channel_after)) - channel->flags |= IEEE80211_CHAN_NO_FAT_ABOVE; + channel->flags |= IEEE80211_CHAN_NO_HT40PLUS; else - channel->flags &= ~IEEE80211_CHAN_NO_FAT_ABOVE; + channel->flags &= ~IEEE80211_CHAN_NO_HT40PLUS; } static void reg_process_ht_flags_band(struct wiphy *wiphy, -- 1.6.0.6 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 3/5] mac80211: check if HT40+/- is allowed before sending assoc 2009-05-02 4:37 [PATCH 0/5] cfg80211: HT bandwidth checks Luis R. Rodriguez 2009-05-02 4:37 ` [PATCH 1/5] cfg80211: Process regulatory max bandwidth checks for HT40 Luis R. Rodriguez 2009-05-02 4:37 ` [PATCH 2/5] wireless: rename IEEE80211_CHAN_NO_FAT_* to HT40-/+ Luis R. Rodriguez @ 2009-05-02 4:37 ` Luis R. Rodriguez 2009-05-02 4:37 ` [PATCH 4/5] cfg80211: check allowed channel type upon userspace requests Luis R. Rodriguez 2009-05-02 4:37 ` [PATCH 5/5] mac80211/cfg80211: move wiphy specific debugfs entries to cfg80211 Luis R. Rodriguez 4 siblings, 0 replies; 8+ messages in thread From: Luis R. Rodriguez @ 2009-05-02 4:37 UTC (permalink / raw) To: linville, johannes; +Cc: linux-wireless, Luis R. Rodriguez We weren't checking this at all. Signed-off-by: Luis R. Rodriguez <lrodriguez@atheros.com> --- net/mac80211/mlme.c | 8 ++++++-- 1 files changed, 6 insertions(+), 2 deletions(-) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 02f93fa..b1ed8c9 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -122,10 +122,14 @@ static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata, (hti->ht_param & IEEE80211_HT_PARAM_CHAN_WIDTH_ANY)) { switch(hti->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: - channel_type = NL80211_CHAN_HT40PLUS; + if (!(local->hw.conf.channel->flags & + IEEE80211_CHAN_NO_HT40PLUS)) + channel_type = NL80211_CHAN_HT40PLUS; break; case IEEE80211_HT_PARAM_CHA_SEC_BELOW: - channel_type = NL80211_CHAN_HT40MINUS; + if (!(local->hw.conf.channel->flags & + IEEE80211_CHAN_NO_HT40MINUS)) + channel_type = NL80211_CHAN_HT40MINUS; break; } } -- 1.6.0.6 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 4/5] cfg80211: check allowed channel type upon userspace requests 2009-05-02 4:37 [PATCH 0/5] cfg80211: HT bandwidth checks Luis R. Rodriguez ` (2 preceding siblings ...) 2009-05-02 4:37 ` [PATCH 3/5] mac80211: check if HT40+/- is allowed before sending assoc Luis R. Rodriguez @ 2009-05-02 4:37 ` Luis R. Rodriguez 2009-05-02 4:37 ` [PATCH 5/5] mac80211/cfg80211: move wiphy specific debugfs entries to cfg80211 Luis R. Rodriguez 4 siblings, 0 replies; 8+ messages in thread From: Luis R. Rodriguez @ 2009-05-02 4:37 UTC (permalink / raw) To: linville, johannes; +Cc: linux-wireless, Luis R. Rodriguez Thanks to nl80211 userspace can be very specific upon device configuration. Before processing the request for the new HT40 channel types (HT40- or HT40+) we need to ensure we can use them regulatory-wise. This wasn't required with wireless extensions as specifying the channel type wasn't not available and configuration was done towards the end implicitly upon association or reception of beacons from the AP. For the new nl80211 we have to check this when configuring the interfaces explicitly. Signed-off-by: Luis R. Rodriguez <lrodriguez@atheros.com> --- net/wireless/nl80211.c | 39 +++++++++++++++++---------------------- 1 files changed, 17 insertions(+), 22 deletions(-) diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 3c53c5c..401b691 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -487,7 +487,7 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT; struct ieee80211_channel *chan; struct ieee80211_sta_ht_cap *ht_cap; - u32 freq, sec_freq; + u32 freq; if (!rdev->ops->set_channel) { result = -EOPNOTSUPP; @@ -513,33 +513,28 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) if (!chan || chan->flags & IEEE80211_CHAN_DISABLED) goto bad_res; - if (channel_type == NL80211_CHAN_HT40MINUS) - sec_freq = freq - 20; - else if (channel_type == NL80211_CHAN_HT40PLUS) - sec_freq = freq + 20; - else - sec_freq = 0; - - ht_cap = &rdev->wiphy.bands[chan->band]->ht_cap; - - /* no HT capabilities */ - if (channel_type != NL80211_CHAN_NO_HT && - !ht_cap->ht_supported) + if (channel_type == NL80211_CHAN_HT40MINUS && + (chan->flags & IEEE80211_CHAN_NO_HT40MINUS)) + goto bad_res; + else if (channel_type == NL80211_CHAN_HT40PLUS && + (chan->flags & IEEE80211_CHAN_NO_HT40PLUS)) goto bad_res; - if (sec_freq) { - struct ieee80211_channel *schan; + /* + * At this point we know if that if HT40 was requested + * we are allowed to use it and the extension channel + * exists. + */ - /* no 40 MHz capabilities */ + ht_cap = &rdev->wiphy.bands[chan->band]->ht_cap; + + /* no HT capabilities or intolerant */ + if (channel_type != NL80211_CHAN_NO_HT) { + if (!ht_cap->ht_supported) + goto bad_res; if (!(ht_cap->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) || (ht_cap->cap & IEEE80211_HT_CAP_40MHZ_INTOLERANT)) goto bad_res; - - schan = ieee80211_get_channel(&rdev->wiphy, sec_freq); - - /* Secondary channel not allowed */ - if (!schan || schan->flags & IEEE80211_CHAN_DISABLED) - goto bad_res; } result = rdev->ops->set_channel(&rdev->wiphy, chan, -- 1.6.0.6 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 5/5] mac80211/cfg80211: move wiphy specific debugfs entries to cfg80211 2009-05-02 4:37 [PATCH 0/5] cfg80211: HT bandwidth checks Luis R. Rodriguez ` (3 preceding siblings ...) 2009-05-02 4:37 ` [PATCH 4/5] cfg80211: check allowed channel type upon userspace requests Luis R. Rodriguez @ 2009-05-02 4:37 ` Luis R. Rodriguez 4 siblings, 0 replies; 8+ messages in thread From: Luis R. Rodriguez @ 2009-05-02 4:37 UTC (permalink / raw) To: linville, johannes; +Cc: linux-wireless, Luis R. Rodriguez This moves the cfg80211 specific stuff to new cfg80211 debugfs entries. Non-mac80211 will also get these entries now. There were only 4 which we take: rts_threshold fragmentation_threshold short_retry_limit long_retry_limit Signed-off-by: Luis R. Rodriguez <lrodriguez@atheros.com> --- net/mac80211/debugfs.c | 16 ---------- net/mac80211/ieee80211_i.h | 4 -- net/wireless/Kconfig | 8 +++++ net/wireless/Makefile | 1 + net/wireless/core.c | 5 +++ net/wireless/core.h | 11 +++++++ net/wireless/debugfs.c | 70 ++++++++++++++++++++++++++++++++++++++++++++ net/wireless/debugfs.h | 14 +++++++++ 8 files changed, 109 insertions(+), 20 deletions(-) create mode 100644 net/wireless/debugfs.c create mode 100644 net/wireless/debugfs.h diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c index ac79320..e83c029 100644 --- a/net/mac80211/debugfs.c +++ b/net/mac80211/debugfs.c @@ -52,14 +52,6 @@ static const struct file_operations name## _ops = { \ DEBUGFS_READONLY_FILE(frequency, 20, "%d", local->hw.conf.channel->center_freq); -DEBUGFS_READONLY_FILE(rts_threshold, 20, "%d", - local->hw.wiphy->rts_threshold); -DEBUGFS_READONLY_FILE(fragmentation_threshold, 20, "%d", - local->hw.wiphy->frag_threshold); -DEBUGFS_READONLY_FILE(short_retry_limit, 20, "%d", - local->hw.wiphy->retry_short); -DEBUGFS_READONLY_FILE(long_retry_limit, 20, "%d", - local->hw.wiphy->retry_long); DEBUGFS_READONLY_FILE(total_ps_buffered, 20, "%d", local->total_ps_buffered); DEBUGFS_READONLY_FILE(wep_iv, 20, "%#08x", @@ -267,10 +259,6 @@ void debugfs_hw_add(struct ieee80211_local *local) local->debugfs.keys = debugfs_create_dir("keys", phyd); DEBUGFS_ADD(frequency); - DEBUGFS_ADD(rts_threshold); - DEBUGFS_ADD(fragmentation_threshold); - DEBUGFS_ADD(short_retry_limit); - DEBUGFS_ADD(long_retry_limit); DEBUGFS_ADD(total_ps_buffered); DEBUGFS_ADD(wep_iv); DEBUGFS_ADD(tsf); @@ -322,10 +310,6 @@ void debugfs_hw_add(struct ieee80211_local *local) void debugfs_hw_del(struct ieee80211_local *local) { DEBUGFS_DEL(frequency); - DEBUGFS_DEL(rts_threshold); - DEBUGFS_DEL(fragmentation_threshold); - DEBUGFS_DEL(short_retry_limit); - DEBUGFS_DEL(long_retry_limit); DEBUGFS_DEL(total_ps_buffered); DEBUGFS_DEL(wep_iv); DEBUGFS_DEL(tsf); diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 03e0d22..15e8242 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -752,10 +752,6 @@ struct ieee80211_local { struct dentry *rcdir; struct dentry *rcname; struct dentry *frequency; - struct dentry *rts_threshold; - struct dentry *fragmentation_threshold; - struct dentry *short_retry_limit; - struct dentry *long_retry_limit; struct dentry *total_ps_buffered; struct dentry *wep_iv; struct dentry *tsf; diff --git a/net/wireless/Kconfig b/net/wireless/Kconfig index 3c3bc9e..4500549 100644 --- a/net/wireless/Kconfig +++ b/net/wireless/Kconfig @@ -10,6 +10,14 @@ config CFG80211_REG_DEBUG If unsure, say N. +config CFG80211_DEBUGFS + bool "cfg80211 DebugFS entries" + depends on CFG80211 && DEBUG_FS + ---help--- + You can enable this if you want to debugfs entries for cfg80211. + + If unsure, say N. + config WIRELESS_OLD_REGULATORY bool "Old wireless static regulatory definitions" default n diff --git a/net/wireless/Makefile b/net/wireless/Makefile index 14ea01c..f78c483 100644 --- a/net/wireless/Makefile +++ b/net/wireless/Makefile @@ -6,6 +6,7 @@ obj-$(CONFIG_LIB80211_CRYPT_CCMP) += lib80211_crypt_ccmp.o obj-$(CONFIG_LIB80211_CRYPT_TKIP) += lib80211_crypt_tkip.o cfg80211-y += core.o sysfs.o radiotap.o util.o reg.o scan.o nl80211.o mlme.o ibss.o +cfg80211-$(CONFIG_CFG80211_DEBUGFS) += debugfs.o cfg80211-$(CONFIG_WIRELESS_EXT) += wext-compat.o ccflags-y += -D__CHECK_ENDIAN__ diff --git a/net/wireless/core.c b/net/wireless/core.c index 2006a4e..b07e630 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -17,6 +17,7 @@ #include "nl80211.h" #include "core.h" #include "sysfs.h" +#include "debugfs.h" /* name for sysfs, %d is appended */ #define PHY_NAME "phy" @@ -375,6 +376,8 @@ int wiphy_register(struct wiphy *wiphy) nl80211_send_reg_change_event(&request); } + cfg80211_debugfs_drv_add(drv); + res = 0; out_unlock: mutex_unlock(&cfg80211_mutex); @@ -405,6 +408,8 @@ void wiphy_unregister(struct wiphy *wiphy) /* unlock again before freeing */ mutex_unlock(&drv->mtx); + cfg80211_debugfs_drv_del(drv); + /* If this device got a regulatory hint tell core its * free to listen now to a new shiny device regulatory hint */ reg_device_remove(wiphy); diff --git a/net/wireless/core.h b/net/wireless/core.h index 3e49d33..5756e80 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h @@ -10,6 +10,7 @@ #include <linux/netdevice.h> #include <linux/kref.h> #include <linux/rbtree.h> +#include <linux/debugfs.h> #include <net/genetlink.h> #include <net/cfg80211.h> #include "reg.h" @@ -50,6 +51,16 @@ struct cfg80211_registered_device { struct cfg80211_scan_request *scan_req; /* protected by RTNL */ unsigned long suspend_at; +#ifdef CONFIG_MAC80211_DEBUGFS + /* Debugfs entries */ + struct wiphy_debugfsdentries { + struct dentry *rts_threshold; + struct dentry *fragmentation_threshold; + struct dentry *short_retry_limit; + struct dentry *long_retry_limit; + } debugfs; +#endif + /* must be last because of the way we do wiphy_priv(), * and it should at least be aligned to NETDEV_ALIGN */ struct wiphy wiphy __attribute__((__aligned__(NETDEV_ALIGN))); diff --git a/net/wireless/debugfs.c b/net/wireless/debugfs.c new file mode 100644 index 0000000..3211e0e --- /dev/null +++ b/net/wireless/debugfs.c @@ -0,0 +1,70 @@ +/* + * cfg80211 debugfs + * + * Copyright 2009 Luis R. Rodriguez <lrodriguez@atheros.com> + * Copyright 2007 Johannes Berg <johannes@sipsolutions.net> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include "core.h" +#include "debugfs.h" + +static int cfg80211_open_file_generic(struct inode *inode, struct file *file) +{ + file->private_data = inode->i_private; + return 0; +} + +#define DEBUGFS_READONLY_FILE(name, buflen, fmt, value...) \ +static ssize_t name## _read(struct file *file, char __user *userbuf, \ + size_t count, loff_t *ppos) \ +{ \ + struct wiphy *wiphy= file->private_data; \ + char buf[buflen]; \ + int res; \ + \ + res = scnprintf(buf, buflen, fmt "\n", ##value); \ + return simple_read_from_buffer(userbuf, count, ppos, buf, res); \ +} \ + \ +static const struct file_operations name## _ops = { \ + .read = name## _read, \ + .open = cfg80211_open_file_generic, \ +}; + +DEBUGFS_READONLY_FILE(rts_threshold, 20, "%d", + wiphy->rts_threshold) +DEBUGFS_READONLY_FILE(fragmentation_threshold, 20, "%d", + wiphy->frag_threshold); +DEBUGFS_READONLY_FILE(short_retry_limit, 20, "%d", + wiphy->retry_short) +DEBUGFS_READONLY_FILE(long_retry_limit, 20, "%d", + wiphy->retry_long); + +#define DEBUGFS_ADD(name) \ + drv->debugfs.name = debugfs_create_file(#name, S_IRUGO, phyd, \ + &drv->wiphy, &name## _ops); +#define DEBUGFS_DEL(name) \ + debugfs_remove(drv->debugfs.name); \ + drv->debugfs.name = NULL; + +void cfg80211_debugfs_drv_add(struct cfg80211_registered_device *drv) +{ + struct dentry *phyd = drv->wiphy.debugfsdir; + + DEBUGFS_ADD(rts_threshold); + DEBUGFS_ADD(fragmentation_threshold); + DEBUGFS_ADD(short_retry_limit); + DEBUGFS_ADD(long_retry_limit); +} + +void cfg80211_debugfs_drv_del(struct cfg80211_registered_device *drv) +{ + DEBUGFS_DEL(rts_threshold); + DEBUGFS_DEL(fragmentation_threshold); + DEBUGFS_DEL(short_retry_limit); + DEBUGFS_DEL(long_retry_limit); +} diff --git a/net/wireless/debugfs.h b/net/wireless/debugfs.h new file mode 100644 index 0000000..c226983 --- /dev/null +++ b/net/wireless/debugfs.h @@ -0,0 +1,14 @@ +#ifndef __CFG80211_DEBUGFS_H +#define __CFG80211_DEBUGFS_H + +#ifdef CONFIG_CFG80211_DEBUGFS +void cfg80211_debugfs_drv_add(struct cfg80211_registered_device *drv); +void cfg80211_debugfs_drv_del(struct cfg80211_registered_device *drv); +#else +static inline +void cfg80211_debugfs_drv_add(struct cfg80211_registered_device *drv) {} +static inline +void cfg80211_debugfs_drv_del(struct cfg80211_registered_device *drv) {} +#endif + +#endif /* __CFG80211_DEBUGFS_H */ -- 1.6.0.6 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 0/5] wireless: listen to bandwidths preferences @ 2009-04-02 22:26 Luis R. Rodriguez 2009-04-02 22:26 ` [PATCH 1/5] cfg80211: Process regulatory max bandwidth checks for HT40 Luis R. Rodriguez 0 siblings, 1 reply; 8+ messages in thread From: Luis R. Rodriguez @ 2009-04-02 22:26 UTC (permalink / raw) To: linville, johannes; +Cc: linux-wireless, Luis R. Rodriguez This is an interim fix for dealing with bandwidth checks as this will all be reworked later. We avoid problems in the future by not exposing anything new over through an API. Debugfs can be used to debug these new flags. Luis R. Rodriguez (5): cfg80211: Process regulatory max bandwidth checks for HT40 wireless: rename IEEE80211_CHAN_NO_FAT_* to HT40-/+ mac80211: check if HT40+/- is allowed before sending assoc cfg80211: check allowed channel type upon userspace requests mac80211: expose HT channel flags through debugfs drivers/net/wireless/ath/regd.c | 10 +- drivers/net/wireless/iwlwifi/iwl-core.c | 4 +- drivers/net/wireless/iwlwifi/iwl-eeprom.c | 8 +- include/net/wireless.h | 23 +++-- net/mac80211/debugfs.c | 15 +++ net/mac80211/ht.c | 11 ++- net/mac80211/ieee80211_i.h | 3 + net/mac80211/mlme.c | 4 +- net/wireless/nl80211.c | 18 +++ net/wireless/reg.c | 194 ++++++++++++++++++++++------ 10 files changed, 226 insertions(+), 64 deletions(-) ^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 1/5] cfg80211: Process regulatory max bandwidth checks for HT40 2009-04-02 22:26 [PATCH 0/5] wireless: listen to bandwidths preferences Luis R. Rodriguez @ 2009-04-02 22:26 ` Luis R. Rodriguez 2009-04-03 9:22 ` Johannes Berg 0 siblings, 1 reply; 8+ messages in thread From: Luis R. Rodriguez @ 2009-04-02 22:26 UTC (permalink / raw) To: linville, johannes; +Cc: linux-wireless, Luis R. Rodriguez We are not correctly listening to the regulatory max bandwidth settings. To actually make use of it we need to redesign things a bit. This patch does the work for that. We do this to so we can obey to regulatory rules accordingly for use of HT40. We end up dealing with HT40 by having two passes for each channel. The first check will see if a 20 MHz channel fits into the channel's center freq on a given frequency range. We check for a 20 MHz banwidth channel as that is the maximum an individual channel will use, at least for now. The first pass will go ahead and check if the regulatory rule for that given center of frequency allows 40 MHz bandwidths and we use this to determine whether or not the channel supports HT40 or not. So to support HT40 you'll need at a regulatory rule that allows you to use 40 MHz channels but you're channel must also be enabled and support 20 MHz by itself. The second pass is done after we do the regulatory checks over an device's supported channel list. On each channel we'll check if the control channel and the extension both: o exist o are enabled o regulatory allows 40 MHz bandwidth on its frequency range This work allows allows us to idependently check for HT40- and HT40+. Signed-off-by: Luis R. Rodriguez <lrodriguez@atheros.com> --- drivers/net/wireless/ath/regd.c | 10 +- include/net/wireless.h | 15 ++- net/wireless/reg.c | 194 ++++++++++++++++++++++++++++++--------- 3 files changed, 169 insertions(+), 50 deletions(-) diff --git a/drivers/net/wireless/ath/regd.c b/drivers/net/wireless/ath/regd.c index 4b5c851..a90c7cf 100644 --- a/drivers/net/wireless/ath/regd.c +++ b/drivers/net/wireless/ath/regd.c @@ -201,8 +201,10 @@ ath_reg_apply_beaconing_flags(struct wiphy *wiphy, continue; if (initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) { - r = freq_reg_info(wiphy, ch->center_freq, - &bandwidth, ®_rule); + r = freq_reg_info(wiphy, + ch->center_freq, + bandwidth, + ®_rule); if (r) continue; /* @@ -266,7 +268,7 @@ ath_reg_apply_active_scan_flags(struct wiphy *wiphy, */ ch = &sband->channels[11]; /* CH 12 */ - r = freq_reg_info(wiphy, ch->center_freq, &bandwidth, ®_rule); + r = freq_reg_info(wiphy, ch->center_freq, bandwidth, ®_rule); if (!r) { if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN)) if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN) @@ -274,7 +276,7 @@ ath_reg_apply_active_scan_flags(struct wiphy *wiphy, } ch = &sband->channels[12]; /* CH 13 */ - r = freq_reg_info(wiphy, ch->center_freq, &bandwidth, ®_rule); + r = freq_reg_info(wiphy, ch->center_freq, bandwidth, ®_rule); if (!r) { if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN)) if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN) diff --git a/include/net/wireless.h b/include/net/wireless.h index 64a7620..e3077e1 100644 --- a/include/net/wireless.h +++ b/include/net/wireless.h @@ -44,6 +44,9 @@ enum ieee80211_band { * is not permitted. * @IEEE80211_CHAN_NO_FAT_BELOW: extension channel below this channel * is not permitted. + * @IEEE80211_CHAN_NO_HT40: indicates no HT40 is allowed at all, + * when this is set %IEEE80211_CHAN_NO_FAT_ABOVE and + * %IEEE80211_CHAN_NO_FAT_BELOW will also be set. */ enum ieee80211_channel_flags { IEEE80211_CHAN_DISABLED = 1<<0, @@ -52,6 +55,7 @@ enum ieee80211_channel_flags { IEEE80211_CHAN_RADAR = 1<<3, IEEE80211_CHAN_NO_FAT_ABOVE = 1<<4, IEEE80211_CHAN_NO_FAT_BELOW = 1<<5, + IEEE80211_CHAN_NO_HT40 = 1<<6, }; /** @@ -449,9 +453,10 @@ extern void wiphy_apply_custom_regulatory( * 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 - * @bandwidth: the bandwidth requirement you have in KHz, if you do not have one - * you can set this to 0. If this frequency is allowed we then set - * this value to the maximum allowed bandwidth. + * @desired_bw_khz: the desired max bandwidth you want to use per + * channel. Note that this is still 20 MHz if you want to use HT40 + * as HT40 makes use of two channels for its 40 MHz width bandwidth. + * If set to 0 we'll assume you want the standard 20 MHz. * @reg_rule: the regulatory rule which we have for this frequency * * Use this function to get the regulatory rule for a specific frequency on @@ -466,7 +471,9 @@ extern void wiphy_apply_custom_regulatory( * freq_in_rule_band() for our current definition of a band -- this is purely * subjective and right now its 802.11 specific. */ -extern int freq_reg_info(struct wiphy *wiphy, u32 center_freq, u32 *bandwidth, +extern int freq_reg_info(struct wiphy *wiphy, + u32 center_freq, + u32 desired_bw_khz, const struct ieee80211_reg_rule **reg_rule); #endif /* __NET_WIRELESS_H */ diff --git a/net/wireless/reg.c b/net/wireless/reg.c index a3ed913..91f7b34 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -49,12 +49,6 @@ static struct regulatory_request *last_request; /* To trigger userspace events */ static struct platform_device *reg_pdev; -/* Keep the ordering from large to small */ -static u32 supported_bandwidths[] = { - MHZ_TO_KHZ(40), - MHZ_TO_KHZ(20), -}; - /* * Central wireless core regulatory domains, we only need two, * the current one and a world regulatory domain in case we have no @@ -436,19 +430,20 @@ static bool is_valid_rd(const struct ieee80211_regdomain *rd) return true; } -/* Returns value in KHz */ -static u32 freq_max_bandwidth(const struct ieee80211_freq_range *freq_range, - u32 freq) +static bool reg_does_bw_fit(const struct ieee80211_freq_range *freq_range, + u32 center_freq_khz, + u32 bw_khz) { - unsigned int i; - for (i = 0; i < ARRAY_SIZE(supported_bandwidths); i++) { - u32 start_freq_khz = freq - supported_bandwidths[i]/2; - u32 end_freq_khz = freq + supported_bandwidths[i]/2; - if (start_freq_khz >= freq_range->start_freq_khz && - end_freq_khz <= freq_range->end_freq_khz) - return supported_bandwidths[i]; - } - return 0; + u32 start_freq_khz, end_freq_khz; + + start_freq_khz = center_freq_khz - (bw_khz/2); + end_freq_khz = center_freq_khz + (bw_khz/2); + + if (start_freq_khz >= freq_range->start_freq_khz && + end_freq_khz <= freq_range->end_freq_khz) + return true; + + return false; } /** @@ -848,14 +843,17 @@ static u32 map_regdom_flags(u32 rd_flags) static int freq_reg_info_regd(struct wiphy *wiphy, u32 center_freq, - u32 *bandwidth, + u32 desired_bw_khz, const struct ieee80211_reg_rule **reg_rule, const struct ieee80211_regdomain *custom_regd) { int i; bool band_rule_found = false; const struct ieee80211_regdomain *regd; - u32 max_bandwidth = 0; + bool bw_fits = false; + + if (!desired_bw_khz) + desired_bw_khz = MHZ_TO_KHZ(20); regd = custom_regd ? custom_regd : cfg80211_regdomain; @@ -888,37 +886,53 @@ static int freq_reg_info_regd(struct wiphy *wiphy, if (!band_rule_found) band_rule_found = freq_in_rule_band(fr, center_freq); - max_bandwidth = freq_max_bandwidth(fr, center_freq); + bw_fits = reg_does_bw_fit(fr, + center_freq, + desired_bw_khz); - if (max_bandwidth && *bandwidth <= max_bandwidth) { + if (band_rule_found && bw_fits) { *reg_rule = rr; - *bandwidth = max_bandwidth; - break; + return 0; } } if (!band_rule_found) return -ERANGE; - return !max_bandwidth; + return -EINVAL; } EXPORT_SYMBOL(freq_reg_info); -int freq_reg_info(struct wiphy *wiphy, u32 center_freq, u32 *bandwidth, - const struct ieee80211_reg_rule **reg_rule) +int freq_reg_info(struct wiphy *wiphy, + u32 center_freq, + u32 desired_bw_khz, + const struct ieee80211_reg_rule **reg_rule) { - return freq_reg_info_regd(wiphy, center_freq, - bandwidth, reg_rule, NULL); + return freq_reg_info_regd(wiphy, + center_freq, + desired_bw_khz, + reg_rule, + NULL); } +/* + * Note that right now we assume the desired channel bandwidth + * is always 20 MHz for each individual channel (HT40 uses 20 MHz + * per channel, the primary and the extension channel). To support + * smaller custom bandwidths such as 5 MHz or 10 MHz we'll need a + * new ieee80211_channel.target_bw and re run the regulatory check + * on the wiphy with the target_bw specified. Then we can simply use + * that below for the desired_bw_khz below. + */ static void handle_channel(struct wiphy *wiphy, enum ieee80211_band band, unsigned int chan_idx) { int r; - u32 flags; - u32 max_bandwidth = 0; + u32 flags, bw_flags = 0; + u32 desired_bw_khz = MHZ_TO_KHZ(20); const struct ieee80211_reg_rule *reg_rule = NULL; const struct ieee80211_power_rule *power_rule = NULL; + const struct ieee80211_freq_range *freq_range = NULL; struct ieee80211_supported_band *sband; struct ieee80211_channel *chan; struct wiphy *request_wiphy = NULL; @@ -933,8 +947,10 @@ static void handle_channel(struct wiphy *wiphy, enum ieee80211_band band, flags = chan->orig_flags; - r = freq_reg_info(wiphy, MHZ_TO_KHZ(chan->center_freq), - &max_bandwidth, ®_rule); + r = freq_reg_info(wiphy, + MHZ_TO_KHZ(chan->center_freq), + desired_bw_khz, + ®_rule); if (r) { /* @@ -977,6 +993,10 @@ static void handle_channel(struct wiphy *wiphy, enum ieee80211_band band, } power_rule = ®_rule->power_rule; + freq_range = ®_rule->freq_range; + + if (freq_range->max_bandwidth_khz < MHZ_TO_KHZ(40)) + bw_flags = IEEE80211_CHAN_NO_HT40; if (last_request->initiator == NL80211_REGDOM_SET_BY_DRIVER && request_wiphy && request_wiphy == wiphy && @@ -987,19 +1007,19 @@ static void handle_channel(struct wiphy *wiphy, enum ieee80211_band band, * settings */ chan->flags = chan->orig_flags = - map_regdom_flags(reg_rule->flags); + map_regdom_flags(reg_rule->flags) | bw_flags; chan->max_antenna_gain = chan->orig_mag = (int) MBI_TO_DBI(power_rule->max_antenna_gain); - chan->max_bandwidth = KHZ_TO_MHZ(max_bandwidth); + chan->max_bandwidth = KHZ_TO_MHZ(desired_bw_khz); chan->max_power = chan->orig_mpwr = (int) MBM_TO_DBM(power_rule->max_eirp); return; } - chan->flags = flags | map_regdom_flags(reg_rule->flags); + chan->flags = flags | bw_flags | map_regdom_flags(reg_rule->flags); chan->max_antenna_gain = min(chan->orig_mag, (int) MBI_TO_DBI(power_rule->max_antenna_gain)); - chan->max_bandwidth = KHZ_TO_MHZ(max_bandwidth); + chan->max_bandwidth = KHZ_TO_MHZ(desired_bw_khz); if (chan->orig_mpwr) chan->max_power = min(chan->orig_mpwr, (int) MBM_TO_DBM(power_rule->max_eirp)); @@ -1149,6 +1169,84 @@ static void reg_process_beacons(struct wiphy *wiphy) wiphy_update_beacon_reg(wiphy); } +static void reg_process_ht_flags_channel(struct wiphy *wiphy, + enum ieee80211_band band, + unsigned int chan_idx) +{ + struct ieee80211_supported_band *sband; + struct ieee80211_channel *channel, *channel_before, *channel_after; + unsigned int i; + + assert_cfg80211_lock(); + + sband = wiphy->bands[band]; + BUG_ON(chan_idx >= sband->n_channels); + channel = &sband->channels[chan_idx]; + + if (channel->flags & + (IEEE80211_CHAN_DISABLED | IEEE80211_CHAN_NO_HT40)) { + channel->flags |= IEEE80211_CHAN_NO_FAT_ABOVE | + IEEE80211_CHAN_NO_FAT_BELOW; + return; + } + + /* + * We need to ensure the extension channels exist to + * be able to use HT40- or HT40+, this finds them (or not) + */ + for (i = 0; i < sband->n_channels; i++) { + struct ieee80211_channel *c = &sband->channels[i]; + if (c->center_freq == (channel->center_freq - 20)) + channel_before = c; + if (c->center_freq == (channel->center_freq + 20)) + channel_after = c; + } + + /* + * Please note that this assumes target bandwidth is 20 MHz, + * if that ever changes we also need to change the below logic + * to include that as well. + */ + if (!channel_before || (channel_before->flags & + (IEEE80211_CHAN_DISABLED | IEEE80211_CHAN_NO_HT40))) + channel->flags |= IEEE80211_CHAN_NO_FAT_BELOW; + else + channel->flags &= ~IEEE80211_CHAN_NO_FAT_BELOW; + + if (!channel_after || (channel_after->flags & + (IEEE80211_CHAN_DISABLED | IEEE80211_CHAN_NO_HT40))) + channel->flags |= IEEE80211_CHAN_NO_FAT_ABOVE; + else + channel->flags &= ~IEEE80211_CHAN_NO_FAT_ABOVE; +} + +static void reg_process_ht_flags_band(struct wiphy *wiphy, + enum ieee80211_band band) +{ + unsigned int i; + struct ieee80211_supported_band *sband; + + BUG_ON(!wiphy->bands[band]); + sband = wiphy->bands[band]; + + for (i = 0; i < sband->n_channels; i++) + reg_process_ht_flags_channel(wiphy, band, i); +} + +static void reg_process_ht_flags(struct wiphy *wiphy) +{ + enum ieee80211_band band; + + if (!wiphy) + return; + + for (band = 0; band < IEEE80211_NUM_BANDS; band++) { + if (wiphy->bands[band]) + reg_process_ht_flags_band(wiphy, band); + } + +} + void wiphy_update_regulatory(struct wiphy *wiphy, enum nl80211_reg_initiator initiator) { @@ -1162,6 +1260,7 @@ void wiphy_update_regulatory(struct wiphy *wiphy, } out: reg_process_beacons(wiphy); + reg_process_ht_flags(wiphy); if (wiphy->reg_notifier) wiphy->reg_notifier(wiphy, last_request); } @@ -1172,9 +1271,11 @@ static void handle_channel_custom(struct wiphy *wiphy, const struct ieee80211_regdomain *regd) { int r; - u32 max_bandwidth = 0; + u32 desired_bw_khz = MHZ_TO_KHZ(20); + u32 bw_flags = 0; const struct ieee80211_reg_rule *reg_rule = NULL; const struct ieee80211_power_rule *power_rule = NULL; + const struct ieee80211_freq_range *freq_range = NULL; struct ieee80211_supported_band *sband; struct ieee80211_channel *chan; @@ -1182,8 +1283,11 @@ static void handle_channel_custom(struct wiphy *wiphy, BUG_ON(chan_idx >= sband->n_channels); chan = &sband->channels[chan_idx]; - r = freq_reg_info_regd(wiphy, MHZ_TO_KHZ(chan->center_freq), - &max_bandwidth, ®_rule, regd); + r = freq_reg_info_regd(wiphy, + MHZ_TO_KHZ(chan->center_freq), + desired_bw_khz, + ®_rule, + regd); if (r) { chan->flags = IEEE80211_CHAN_DISABLED; @@ -1191,10 +1295,16 @@ static void handle_channel_custom(struct wiphy *wiphy, } power_rule = ®_rule->power_rule; + freq_range = ®_rule->freq_range; + + if (freq_range->max_bandwidth_khz < MHZ_TO_KHZ(40)) + bw_flags = IEEE80211_CHAN_NO_HT40 | + IEEE80211_CHAN_NO_FAT_BELOW | + IEEE80211_CHAN_NO_FAT_ABOVE; - chan->flags |= map_regdom_flags(reg_rule->flags); + 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_bandwidth = KHZ_TO_MHZ(max_bandwidth); + chan->max_bandwidth = KHZ_TO_MHZ(desired_bw_khz); chan->max_power = (int) MBM_TO_DBM(power_rule->max_eirp); } -- 1.6.0.6 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH 1/5] cfg80211: Process regulatory max bandwidth checks for HT40 2009-04-02 22:26 ` [PATCH 1/5] cfg80211: Process regulatory max bandwidth checks for HT40 Luis R. Rodriguez @ 2009-04-03 9:22 ` Johannes Berg 0 siblings, 0 replies; 8+ messages in thread From: Johannes Berg @ 2009-04-03 9:22 UTC (permalink / raw) To: Luis R. Rodriguez; +Cc: linville, linux-wireless [-- Attachment #1: Type: text/plain, Size: 472 bytes --] On Thu, 2009-04-02 at 18:26 -0400, Luis R. Rodriguez wrote: > enum ieee80211_channel_flags { > IEEE80211_CHAN_DISABLED = 1<<0, > @@ -52,6 +55,7 @@ enum ieee80211_channel_flags { > IEEE80211_CHAN_RADAR = 1<<3, > IEEE80211_CHAN_NO_FAT_ABOVE = 1<<4, > IEEE80211_CHAN_NO_FAT_BELOW = 1<<5, > + IEEE80211_CHAN_NO_HT40 = 1<<6, > }; As we've talked about, just a little work and you can live without this constant [just for John's benefit] johannes [-- Attachment #2: This is a digitally signed message part --] [-- Type: application/pgp-signature, Size: 836 bytes --] ^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2009-05-02 4:37 UTC | newest] Thread overview: 8+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2009-05-02 4:37 [PATCH 0/5] cfg80211: HT bandwidth checks Luis R. Rodriguez 2009-05-02 4:37 ` [PATCH 1/5] cfg80211: Process regulatory max bandwidth checks for HT40 Luis R. Rodriguez 2009-05-02 4:37 ` [PATCH 2/5] wireless: rename IEEE80211_CHAN_NO_FAT_* to HT40-/+ Luis R. Rodriguez 2009-05-02 4:37 ` [PATCH 3/5] mac80211: check if HT40+/- is allowed before sending assoc Luis R. Rodriguez 2009-05-02 4:37 ` [PATCH 4/5] cfg80211: check allowed channel type upon userspace requests Luis R. Rodriguez 2009-05-02 4:37 ` [PATCH 5/5] mac80211/cfg80211: move wiphy specific debugfs entries to cfg80211 Luis R. Rodriguez -- strict thread matches above, loose matches on Subject: below -- 2009-04-02 22:26 [PATCH 0/5] wireless: listen to bandwidths preferences Luis R. Rodriguez 2009-04-02 22:26 ` [PATCH 1/5] cfg80211: Process regulatory max bandwidth checks for HT40 Luis R. Rodriguez 2009-04-03 9:22 ` Johannes Berg
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox