aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2012-12-12 11:50:39 -0500
committerJohannes Berg <johannes.berg@intel.com>2013-02-15 03:41:38 -0500
commitc7a6ee27abd46247c1c7edfc49fb935138da7875 (patch)
tree716d3e489fbf1d5f34fd362ef09c985e4de033bf
parent30eb1dc2c43039e0fe278e6f3a288de9f216d70d (diff)
cfg80211: allow drivers to selectively disable 80/160 MHz
Some drivers might support 80 or 160 MHz only on some channels for whatever reason, so allow them to disable these channel widths. Also maintain the new flags when regulatory bandwidth limitations would disable these wide channels. Reviewed-by: Luis R. Rodriguez <mcgrof@do-not-panic.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-rw-r--r--include/net/cfg80211.h12
-rw-r--r--net/wireless/chan.c13
-rw-r--r--net/wireless/reg.c8
3 files changed, 32 insertions, 1 deletions
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index ee11a3db730b..8a9200f2f4a4 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -100,6 +100,16 @@ enum ieee80211_band {
100 * @IEEE80211_CHAN_NO_HT40MINUS: extension channel below this channel 100 * @IEEE80211_CHAN_NO_HT40MINUS: extension channel below this channel
101 * is not permitted. 101 * is not permitted.
102 * @IEEE80211_CHAN_NO_OFDM: OFDM is not allowed on this channel. 102 * @IEEE80211_CHAN_NO_OFDM: OFDM is not allowed on this channel.
103 * @IEEE80211_CHAN_NO_80MHZ: If the driver supports 80 MHz on the band,
104 * this flag indicates that an 80 MHz channel cannot use this
105 * channel as the control or any of the secondary channels.
106 * This may be due to the driver or due to regulatory bandwidth
107 * restrictions.
108 * @IEEE80211_CHAN_NO_160MHZ: If the driver supports 160 MHz on the band,
109 * this flag indicates that an 160 MHz channel cannot use this
110 * channel as the control or any of the secondary channels.
111 * This may be due to the driver or due to regulatory bandwidth
112 * restrictions.
103 */ 113 */
104enum ieee80211_channel_flags { 114enum ieee80211_channel_flags {
105 IEEE80211_CHAN_DISABLED = 1<<0, 115 IEEE80211_CHAN_DISABLED = 1<<0,
@@ -109,6 +119,8 @@ enum ieee80211_channel_flags {
109 IEEE80211_CHAN_NO_HT40PLUS = 1<<4, 119 IEEE80211_CHAN_NO_HT40PLUS = 1<<4,
110 IEEE80211_CHAN_NO_HT40MINUS = 1<<5, 120 IEEE80211_CHAN_NO_HT40MINUS = 1<<5,
111 IEEE80211_CHAN_NO_OFDM = 1<<6, 121 IEEE80211_CHAN_NO_OFDM = 1<<6,
122 IEEE80211_CHAN_NO_80MHZ = 1<<7,
123 IEEE80211_CHAN_NO_160MHZ = 1<<8,
112}; 124};
113 125
114#define IEEE80211_CHAN_NO_HT40 \ 126#define IEEE80211_CHAN_NO_HT40 \
diff --git a/net/wireless/chan.c b/net/wireless/chan.c
index 810c23cfb894..fd556ac05fdb 100644
--- a/net/wireless/chan.c
+++ b/net/wireless/chan.c
@@ -375,6 +375,7 @@ bool cfg80211_chandef_usable(struct wiphy *wiphy,
375 case NL80211_CHAN_WIDTH_80: 375 case NL80211_CHAN_WIDTH_80:
376 if (!vht_cap->vht_supported) 376 if (!vht_cap->vht_supported)
377 return false; 377 return false;
378 prohibited_flags |= IEEE80211_CHAN_NO_80MHZ;
378 width = 80; 379 width = 80;
379 break; 380 break;
380 case NL80211_CHAN_WIDTH_160: 381 case NL80211_CHAN_WIDTH_160:
@@ -382,6 +383,7 @@ bool cfg80211_chandef_usable(struct wiphy *wiphy,
382 return false; 383 return false;
383 if (!(vht_cap->cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ)) 384 if (!(vht_cap->cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ))
384 return false; 385 return false;
386 prohibited_flags |= IEEE80211_CHAN_NO_160MHZ;
385 width = 160; 387 width = 160;
386 break; 388 break;
387 default: 389 default:
@@ -389,7 +391,16 @@ bool cfg80211_chandef_usable(struct wiphy *wiphy,
389 return false; 391 return false;
390 } 392 }
391 393
392 /* TODO: missing regulatory check on 80/160 bandwidth */ 394 /*
395 * TODO: What if there are only certain 80/160/80+80 MHz channels
396 * allowed by the driver, or only certain combinations?
397 * For 40 MHz the driver can set the NO_HT40 flags, but for
398 * 80/160 MHz and in particular 80+80 MHz this isn't really
399 * feasible and we only have NO_80MHZ/NO_160MHZ so far but
400 * no way to cover 80+80 MHz or more complex restrictions.
401 * Note that such restrictions also need to be advertised to
402 * userspace, for example for P2P channel selection.
403 */
393 404
394 if (width > 20) 405 if (width > 20)
395 prohibited_flags |= IEEE80211_CHAN_NO_OFDM; 406 prohibited_flags |= IEEE80211_CHAN_NO_OFDM;
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index e97d5b071ab6..93ab840957a0 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -866,6 +866,10 @@ static void handle_channel(struct wiphy *wiphy,
866 866
867 if (freq_range->max_bandwidth_khz < MHZ_TO_KHZ(40)) 867 if (freq_range->max_bandwidth_khz < MHZ_TO_KHZ(40))
868 bw_flags = IEEE80211_CHAN_NO_HT40; 868 bw_flags = IEEE80211_CHAN_NO_HT40;
869 if (freq_range->max_bandwidth_khz < MHZ_TO_KHZ(80))
870 bw_flags |= IEEE80211_CHAN_NO_80MHZ;
871 if (freq_range->max_bandwidth_khz < MHZ_TO_KHZ(160))
872 bw_flags |= IEEE80211_CHAN_NO_160MHZ;
869 873
870 if (lr->initiator == NL80211_REGDOM_SET_BY_DRIVER && 874 if (lr->initiator == NL80211_REGDOM_SET_BY_DRIVER &&
871 request_wiphy && request_wiphy == wiphy && 875 request_wiphy && request_wiphy == wiphy &&
@@ -1264,6 +1268,10 @@ static void handle_channel_custom(struct wiphy *wiphy,
1264 1268
1265 if (freq_range->max_bandwidth_khz < MHZ_TO_KHZ(40)) 1269 if (freq_range->max_bandwidth_khz < MHZ_TO_KHZ(40))
1266 bw_flags = IEEE80211_CHAN_NO_HT40; 1270 bw_flags = IEEE80211_CHAN_NO_HT40;
1271 if (freq_range->max_bandwidth_khz < MHZ_TO_KHZ(80))
1272 bw_flags |= IEEE80211_CHAN_NO_80MHZ;
1273 if (freq_range->max_bandwidth_khz < MHZ_TO_KHZ(160))
1274 bw_flags |= IEEE80211_CHAN_NO_160MHZ;
1267 1275
1268 chan->flags |= map_regdom_flags(reg_rule->flags) | bw_flags; 1276 chan->flags |= map_regdom_flags(reg_rule->flags) | bw_flags;
1269 chan->max_antenna_gain = (int) MBI_TO_DBI(power_rule->max_antenna_gain); 1277 chan->max_antenna_gain = (int) MBI_TO_DBI(power_rule->max_antenna_gain);