aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/nl80211.h2
-rw-r--r--include/net/cfg80211.h11
-rw-r--r--net/wireless/chan.c12
-rw-r--r--net/wireless/nl80211.c32
4 files changed, 50 insertions, 7 deletions
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index f51e3bf93a9..a18760684fc 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -2785,9 +2785,11 @@ enum nl80211_ap_sme_features {
2785 * @NL80211_FEATURE_SK_TX_STATUS: This driver supports reflecting back 2785 * @NL80211_FEATURE_SK_TX_STATUS: This driver supports reflecting back
2786 * TX status to the socket error queue when requested with the 2786 * TX status to the socket error queue when requested with the
2787 * socket option. 2787 * socket option.
2788 * @NL80211_FEATURE_HT_IBSS: This driver supports IBSS with HT datarates.
2788 */ 2789 */
2789enum nl80211_feature_flags { 2790enum nl80211_feature_flags {
2790 NL80211_FEATURE_SK_TX_STATUS = 1 << 0, 2791 NL80211_FEATURE_SK_TX_STATUS = 1 << 0,
2792 NL80211_FEATURE_HT_IBSS = 1 << 1,
2791}; 2793};
2792 2794
2793/** 2795/**
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index f0e82b2e422..3de1c39d03e 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -1149,6 +1149,7 @@ struct cfg80211_ibss_params {
1149 u8 *ssid; 1149 u8 *ssid;
1150 u8 *bssid; 1150 u8 *bssid;
1151 struct ieee80211_channel *channel; 1151 struct ieee80211_channel *channel;
1152 enum nl80211_channel_type channel_type;
1152 u8 *ie; 1153 u8 *ie;
1153 u8 ssid_len, ie_len; 1154 u8 ssid_len, ie_len;
1154 u16 beacon_interval; 1155 u16 beacon_interval;
@@ -3267,6 +3268,16 @@ void cfg80211_report_obss_beacon(struct wiphy *wiphy,
3267 const u8 *frame, size_t len, 3268 const u8 *frame, size_t len,
3268 int freq, gfp_t gfp); 3269 int freq, gfp_t gfp);
3269 3270
3271/*
3272 * cfg80211_can_beacon_sec_chan - test if ht40 on extension channel can be used
3273 * @wiphy: the wiphy
3274 * @chan: main channel
3275 * @channel_type: HT mode
3276 */
3277int cfg80211_can_beacon_sec_chan(struct wiphy *wiphy,
3278 struct ieee80211_channel *chan,
3279 enum nl80211_channel_type channel_type);
3280
3270/* Logging, debugging and troubleshooting/diagnostic helpers. */ 3281/* Logging, debugging and troubleshooting/diagnostic helpers. */
3271 3282
3272/* wiphy_printk helpers, similar to dev_printk */ 3283/* wiphy_printk helpers, similar to dev_printk */
diff --git a/net/wireless/chan.c b/net/wireless/chan.c
index 17cd0c04d13..2fcfe0993ca 100644
--- a/net/wireless/chan.c
+++ b/net/wireless/chan.c
@@ -6,6 +6,7 @@
6 * Copyright 2009 Johannes Berg <johannes@sipsolutions.net> 6 * Copyright 2009 Johannes Berg <johannes@sipsolutions.net>
7 */ 7 */
8 8
9#include <linux/export.h>
9#include <net/cfg80211.h> 10#include <net/cfg80211.h>
10#include "core.h" 11#include "core.h"
11 12
@@ -44,9 +45,9 @@ rdev_freq_to_chan(struct cfg80211_registered_device *rdev,
44 return chan; 45 return chan;
45} 46}
46 47
47static bool can_beacon_sec_chan(struct wiphy *wiphy, 48int cfg80211_can_beacon_sec_chan(struct wiphy *wiphy,
48 struct ieee80211_channel *chan, 49 struct ieee80211_channel *chan,
49 enum nl80211_channel_type channel_type) 50 enum nl80211_channel_type channel_type)
50{ 51{
51 struct ieee80211_channel *sec_chan; 52 struct ieee80211_channel *sec_chan;
52 int diff; 53 int diff;
@@ -75,6 +76,7 @@ static bool can_beacon_sec_chan(struct wiphy *wiphy,
75 76
76 return true; 77 return true;
77} 78}
79EXPORT_SYMBOL(cfg80211_can_beacon_sec_chan);
78 80
79int cfg80211_set_freq(struct cfg80211_registered_device *rdev, 81int cfg80211_set_freq(struct cfg80211_registered_device *rdev,
80 struct wireless_dev *wdev, int freq, 82 struct wireless_dev *wdev, int freq,
@@ -109,8 +111,8 @@ int cfg80211_set_freq(struct cfg80211_registered_device *rdev,
109 switch (channel_type) { 111 switch (channel_type) {
110 case NL80211_CHAN_HT40PLUS: 112 case NL80211_CHAN_HT40PLUS:
111 case NL80211_CHAN_HT40MINUS: 113 case NL80211_CHAN_HT40MINUS:
112 if (!can_beacon_sec_chan(&rdev->wiphy, chan, 114 if (!cfg80211_can_beacon_sec_chan(&rdev->wiphy, chan,
113 channel_type)) { 115 channel_type)) {
114 printk(KERN_DEBUG 116 printk(KERN_DEBUG
115 "cfg80211: Secondary channel not " 117 "cfg80211: Secondary channel not "
116 "allowed to initiate communication\n"); 118 "allowed to initiate communication\n");
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 8a9b4d817ae..ba439664c2e 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -4682,13 +4682,41 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info)
4682 ibss.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]); 4682 ibss.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
4683 } 4683 }
4684 4684
4685 ibss.channel = ieee80211_get_channel(wiphy, 4685 if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) {
4686 nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ])); 4686 enum nl80211_channel_type channel_type;
4687
4688 channel_type = nla_get_u32(
4689 info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]);
4690 if (channel_type != NL80211_CHAN_NO_HT &&
4691 channel_type != NL80211_CHAN_HT20 &&
4692 channel_type != NL80211_CHAN_HT40MINUS &&
4693 channel_type != NL80211_CHAN_HT40PLUS)
4694 return -EINVAL;
4695
4696 if (channel_type != NL80211_CHAN_NO_HT &&
4697 !(wiphy->features & NL80211_FEATURE_HT_IBSS))
4698 return -EINVAL;
4699
4700 ibss.channel_type = channel_type;
4701 } else {
4702 ibss.channel_type = NL80211_CHAN_NO_HT;
4703 }
4704
4705 ibss.channel = rdev_freq_to_chan(rdev,
4706 nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]),
4707 ibss.channel_type);
4687 if (!ibss.channel || 4708 if (!ibss.channel ||
4688 ibss.channel->flags & IEEE80211_CHAN_NO_IBSS || 4709 ibss.channel->flags & IEEE80211_CHAN_NO_IBSS ||
4689 ibss.channel->flags & IEEE80211_CHAN_DISABLED) 4710 ibss.channel->flags & IEEE80211_CHAN_DISABLED)
4690 return -EINVAL; 4711 return -EINVAL;
4691 4712
4713 /* Both channels should be able to initiate communication */
4714 if ((ibss.channel_type == NL80211_CHAN_HT40PLUS ||
4715 ibss.channel_type == NL80211_CHAN_HT40MINUS) &&
4716 !cfg80211_can_beacon_sec_chan(&rdev->wiphy, ibss.channel,
4717 ibss.channel_type))
4718 return -EINVAL;
4719
4692 ibss.channel_fixed = !!info->attrs[NL80211_ATTR_FREQ_FIXED]; 4720 ibss.channel_fixed = !!info->attrs[NL80211_ATTR_FREQ_FIXED];
4693 ibss.privacy = !!info->attrs[NL80211_ATTR_PRIVACY]; 4721 ibss.privacy = !!info->attrs[NL80211_ATTR_PRIVACY];
4694 4722