@@ -100,6 +100,16 @@ enum ieee80211_band {
* @IEEE80211_CHAN_NO_HT40MINUS: extension channel below this channel
* is not permitted.
* @IEEE80211_CHAN_NO_OFDM: OFDM is not allowed on this channel.
+ * @IEEE80211_CHAN_NO_80MHZ: If the driver supports 80 MHz on the band,
+ * this flag indicates that an 80 MHz channel cannot use this
+ * channel as the control or any of the secondary channels.
+ * This may be due to the driver or due to regulatory bandwidth
+ * restrictions.
+ * @IEEE80211_CHAN_NO_160MHZ: If the driver supports 160 MHz on the band,
+ * this flag indicates that an 160 MHz channel cannot use this
+ * channel as the control or any of the secondary channels.
+ * This may be due to the driver or due to regulatory bandwidth
+ * restrictions.
*/
enum ieee80211_channel_flags {
IEEE80211_CHAN_DISABLED = 1<<0,
@@ -109,6 +119,8 @@ enum ieee80211_channel_flags {
IEEE80211_CHAN_NO_HT40PLUS = 1<<4,
IEEE80211_CHAN_NO_HT40MINUS = 1<<5,
IEEE80211_CHAN_NO_OFDM = 1<<6,
+ IEEE80211_CHAN_NO_80MHZ = 1<<7,
+ IEEE80211_CHAN_NO_160MHZ = 1<<8,
};
#define IEEE80211_CHAN_NO_HT40 \
@@ -379,6 +379,7 @@ bool cfg80211_chandef_usable(struct wiphy *wiphy,
case NL80211_CHAN_WIDTH_80:
if (!vht_cap->vht_supported)
return false;
+ prohibited_flags |= IEEE80211_CHAN_NO_80MHZ;
width = 80;
break;
case NL80211_CHAN_WIDTH_160:
@@ -386,6 +387,7 @@ bool cfg80211_chandef_usable(struct wiphy *wiphy,
return false;
if (!(vht_cap->cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ))
return false;
+ prohibited_flags |= IEEE80211_CHAN_NO_160MHZ;
width = 160;
break;
default:
@@ -398,7 +400,10 @@ bool cfg80211_chandef_usable(struct wiphy *wiphy,
* allowed by the driver, or only certain combinations?
* For 40 MHz the driver can set the NO_HT40 flags, but for
* 80/160 MHz and in particular 80+80 MHz this isn't really
- * feasible -- should we ask the driver here?
+ * feasible and we only have NO_80MHZ/NO_160MHZ so far but
+ * no way to cover 80+80 MHz or more complex restrictions.
+ * Note that the restrictions also need to be advertised to
+ * userspace, for example for P2P channel selection.
*/
if (width > 20)
@@ -889,6 +889,10 @@ static void handle_channel(struct wiphy *wiphy,
if (freq_range->max_bandwidth_khz < MHZ_TO_KHZ(40))
bw_flags = IEEE80211_CHAN_NO_HT40;
+ if (freq_range->max_bandwidth_khz < MHZ_TO_KHZ(80))
+ bw_flags |= IEEE80211_CHAN_NO_80MHZ;
+ if (freq_range->max_bandwidth_khz < MHZ_TO_KHZ(160))
+ bw_flags |= IEEE80211_CHAN_NO_160MHZ;
if (lr->initiator == NL80211_REGDOM_SET_BY_DRIVER &&
request_wiphy && request_wiphy == wiphy &&
@@ -1287,6 +1291,10 @@ static void handle_channel_custom(struct wiphy *wiphy,
if (freq_range->max_bandwidth_khz < MHZ_TO_KHZ(40))
bw_flags = IEEE80211_CHAN_NO_HT40;
+ if (freq_range->max_bandwidth_khz < MHZ_TO_KHZ(80))
+ bw_flags |= IEEE80211_CHAN_NO_80MHZ;
+ if (freq_range->max_bandwidth_khz < MHZ_TO_KHZ(160))
+ bw_flags |= IEEE80211_CHAN_NO_160MHZ;
chan->flags |= map_regdom_flags(reg_rule->flags) | bw_flags;
chan->max_antenna_gain = (int) MBI_TO_DBI(power_rule->max_antenna_gain);