* responds to probe-requests in hardware.
* @WIPHY_FLAG_OFFCHAN_TX: Device supports direct off-channel TX.
* @WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL: Device supports remain-on-channel call.
+ * @WIPHY_FLAG_SUPPORTS_5_10_MHZ: Device supports 5 MHz and 10 MHz channels.
*/
enum wiphy_flags {
WIPHY_FLAG_CUSTOM_REGULATORY = BIT(0),
WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD = BIT(19),
WIPHY_FLAG_OFFCHAN_TX = BIT(20),
WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL = BIT(21),
+ WIPHY_FLAG_SUPPORTS_5_10_MHZ = BIT(22),
};
/**
control_freq = chandef->chan->center_freq;
switch (chandef->width) {
+ case NL80211_CHAN_WIDTH_5:
+ case NL80211_CHAN_WIDTH_10:
case NL80211_CHAN_WIDTH_20:
case NL80211_CHAN_WIDTH_20_NOHT:
if (chandef->center_freq1 != control_freq)
int width;
switch (c->width) {
+ case NL80211_CHAN_WIDTH_5:
+ width = 5;
+ break;
+ case NL80211_CHAN_WIDTH_10:
+ width = 10;
+ break;
case NL80211_CHAN_WIDTH_20:
case NL80211_CHAN_WIDTH_20_NOHT:
width = 20;
if (c1->width == c2->width)
return NULL;
+ /*
+ * can't be compatible if one of them is 5 or 10 MHz,
+ * but they don't have the same width.
+ */
+ if (c1->width == NL80211_CHAN_WIDTH_5 ||
+ c1->width == NL80211_CHAN_WIDTH_10 ||
+ c2->width == NL80211_CHAN_WIDTH_5 ||
+ c2->width == NL80211_CHAN_WIDTH_10)
+ return NULL;
+
if (c1->width == NL80211_CHAN_WIDTH_20_NOHT ||
c1->width == NL80211_CHAN_WIDTH_20)
return c2;
u32 bandwidth)
{
struct ieee80211_channel *c;
- u32 freq;
+ u32 freq, start_freq, end_freq;
+
+ if (bandwidth <= 20) {
+ start_freq = center_freq;
+ end_freq = center_freq;
+ } else {
+ start_freq = center_freq - bandwidth/2 + 10;
+ end_freq = center_freq + bandwidth/2 - 10;
+ }
- for (freq = center_freq - bandwidth/2 + 10;
- freq <= center_freq + bandwidth/2 - 10;
- freq += 20) {
+ for (freq = start_freq; freq <= end_freq; freq += 20) {
c = ieee80211_get_channel(wiphy, freq);
if (!c)
return -EINVAL;
u32 prohibited_flags)
{
struct ieee80211_channel *c;
- u32 freq;
+ u32 freq, start_freq, end_freq;
+
+ if (bandwidth <= 20) {
+ start_freq = center_freq;
+ end_freq = center_freq;
+ } else {
+ start_freq = center_freq - bandwidth/2 + 10;
+ end_freq = center_freq + bandwidth/2 - 10;
+ }
- for (freq = center_freq - bandwidth/2 + 10;
- freq <= center_freq + bandwidth/2 - 10;
- freq += 20) {
+ for (freq = start_freq; freq <= end_freq; freq += 20) {
c = ieee80211_get_channel(wiphy, freq);
if (!c)
return false;
control_freq = chandef->chan->center_freq;
switch (chandef->width) {
+ case NL80211_CHAN_WIDTH_5:
+ width = 5;
+ break;
+ case NL80211_CHAN_WIDTH_10:
+ width = 10;
+ break;
case NL80211_CHAN_WIDTH_20:
if (!ht_cap->ht_supported)
return false;
if (width > 20)
prohibited_flags |= IEEE80211_CHAN_NO_OFDM;
+ /* 5 and 10 MHz are only defined for the OFDM PHY */
+ if (width < 20)
+ prohibited_flags |= IEEE80211_CHAN_NO_OFDM;
+
+
if (!cfg80211_secondary_chans_ok(wiphy, chandef->center_freq1,
width, prohibited_flags))
return false;
if ((dev->wiphy.flags & WIPHY_FLAG_TDLS_EXTERNAL_SETUP) &&
nla_put_flag(msg, NL80211_ATTR_TDLS_EXTERNAL_SETUP))
goto nla_put_failure;
+ if ((dev->wiphy.flags & WIPHY_FLAG_SUPPORTS_5_10_MHZ) &&
+ nla_put_flag(msg, WIPHY_FLAG_SUPPORTS_5_10_MHZ))
+ goto nla_put_failure;
(*split_start)++;
if (split)
IEEE80211_CHAN_DISABLED))
return -EINVAL;
+ if ((chandef->width == NL80211_CHAN_WIDTH_5 ||
+ chandef->width == NL80211_CHAN_WIDTH_10) &&
+ !(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_5_10_MHZ))
+ return -EINVAL;
+
return 0;
}
if (!cfg80211_reg_can_beacon(&rdev->wiphy, &ibss.chandef))
return -EINVAL;
- if (ibss.chandef.width > NL80211_CHAN_WIDTH_40)
- return -EINVAL;
- if (ibss.chandef.width != NL80211_CHAN_WIDTH_20_NOHT &&
- !(rdev->wiphy.features & NL80211_FEATURE_HT_IBSS))
+ switch (ibss.chandef.width) {
+ case NL80211_CHAN_WIDTH_20_NOHT:
+ break;
+ case NL80211_CHAN_WIDTH_20:
+ case NL80211_CHAN_WIDTH_40:
+ if (rdev->wiphy.features & NL80211_FEATURE_HT_IBSS)
+ break;
+ default:
return -EINVAL;
+ }
ibss.channel_fixed = !!info->attrs[NL80211_ATTR_FREQ_FIXED];
ibss.privacy = !!info->attrs[NL80211_ATTR_PRIVACY];