diff options
-rw-r--r-- | include/linux/nl80211.h | 2 | ||||
-rw-r--r-- | include/net/cfg80211.h | 11 | ||||
-rw-r--r-- | net/wireless/chan.c | 12 | ||||
-rw-r--r-- | net/wireless/nl80211.c | 32 |
4 files changed, 50 insertions, 7 deletions
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h index f51e3bf93a96..a18760684fc9 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 | */ |
2789 | enum nl80211_feature_flags { | 2790 | enum 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 f0e82b2e4227..3de1c39d03e5 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 | */ | ||
3277 | int 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 17cd0c04d139..2fcfe0993ca2 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 | ||
47 | static bool can_beacon_sec_chan(struct wiphy *wiphy, | 48 | int 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 | } |
79 | EXPORT_SYMBOL(cfg80211_can_beacon_sec_chan); | ||
78 | 80 | ||
79 | int cfg80211_set_freq(struct cfg80211_registered_device *rdev, | 81 | int 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 8a9b4d817ae6..ba439664c2e0 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 | ||