* [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; 11+ 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] 11+ 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; 11+ 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] 11+ 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; 11+ 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] 11+ 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; 11+ 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] 11+ 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; 11+ 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] 11+ messages in thread