+--- a/net/wireless/nl80211.c
++++ b/net/wireless/nl80211.c
+@@ -4539,13 +4539,41 @@ static int nl80211_join_ibss(struct sk_b
+ ibss.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
+ }
+
+- ibss.channel = ieee80211_get_channel(wiphy,
+- nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]));
++ if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) {
++ enum nl80211_channel_type channel_type;
++
++ channel_type = nla_get_u32(
++ info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]);
++ if (channel_type != NL80211_CHAN_NO_HT &&
++ channel_type != NL80211_CHAN_HT20 &&
++ channel_type != NL80211_CHAN_HT40PLUS &&
++ channel_type != NL80211_CHAN_HT40MINUS)
++ return -EINVAL;
++ ibss.channel_type = channel_type;
++ } else {
++ ibss.channel_type = NL80211_CHAN_NO_HT;
++ }
++
++ ibss.channel = rdev_freq_to_chan(rdev,
++ nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]),
++ ibss.channel_type);
+ if (!ibss.channel ||
++ ibss.channel->flags & IEEE80211_CHAN_PASSIVE_SCAN ||
+ ibss.channel->flags & IEEE80211_CHAN_NO_IBSS ||
+- ibss.channel->flags & IEEE80211_CHAN_DISABLED)
++ ibss.channel->flags & IEEE80211_CHAN_RADAR)
+ return -EINVAL;
+
++ /* Both channels should be able to initiate communication */
++ if ((ibss.channel_type == NL80211_CHAN_HT40PLUS ||
++ ibss.channel_type == NL80211_CHAN_HT40MINUS) &&
++ !can_beacon_sec_chan(&rdev->wiphy, ibss.channel,
++ ibss.channel_type)) {
++ printk(KERN_DEBUG
++ "cfg80211: Secondary channel not "
++ "allowed to initiate communication\n");
++ return -EINVAL;
++ }
++
+ ibss.channel_fixed = !!info->attrs[NL80211_ATTR_FREQ_FIXED];
+ ibss.privacy = !!info->attrs[NL80211_ATTR_PRIVACY];
+
+--- a/net/wireless/chan.c
++++ b/net/wireless/chan.c
+@@ -44,7 +44,7 @@ rdev_freq_to_chan(struct cfg80211_regist
+ return chan;
+ }
+
+-static bool can_beacon_sec_chan(struct wiphy *wiphy,
++bool can_beacon_sec_chan(struct wiphy *wiphy,
+ struct ieee80211_channel *chan,
+ enum nl80211_channel_type channel_type)
+ {
+@@ -75,6 +75,7 @@ static bool can_beacon_sec_chan(struct w
+
+ return true;
+ }
++EXPORT_SYMBOL(can_beacon_sec_chan);
+
+ int cfg80211_set_freq(struct cfg80211_registered_device *rdev,
+ struct wireless_dev *wdev, int freq,
+--- a/net/wireless/core.h
++++ b/net/wireless/core.h
+@@ -439,6 +439,9 @@ cfg80211_can_add_interface(struct cfg802
+ struct ieee80211_channel *
+ rdev_freq_to_chan(struct cfg80211_registered_device *rdev,
+ int freq, enum nl80211_channel_type channel_type);
++bool can_beacon_sec_chan(struct wiphy *wiphy,
++ struct ieee80211_channel *chan,
++ enum nl80211_channel_type channel_type);
+ int cfg80211_set_freq(struct cfg80211_registered_device *rdev,
+ struct wireless_dev *wdev, int freq,
+ enum nl80211_channel_type channel_type);
+--- a/net/wireless/scan.c
++++ b/net/wireless/scan.c
+@@ -365,6 +365,19 @@ struct cfg80211_bss *cfg80211_get_bss(st
+ const u8 *ssid, size_t ssid_len,
+ u16 capa_mask, u16 capa_val)
+ {
++ /* call HT version with no HT requirements */
++ return cfg80211_get_bss_ht(wiphy, channel, bssid, ssid, ssid_len,
++ capa_mask, capa_val, NL80211_CHAN_NO_HT);
++}
++EXPORT_SYMBOL(cfg80211_get_bss);
++
++struct cfg80211_bss *cfg80211_get_bss_ht(struct wiphy *wiphy,
++ struct ieee80211_channel *channel,
++ const u8 *bssid,
++ const u8 *ssid, size_t ssid_len,
++ u16 capa_mask, u16 capa_val,
++ enum nl80211_channel_type require_ht)
++{
+ struct cfg80211_registered_device *dev = wiphy_to_dev(wiphy);
+ struct cfg80211_internal_bss *bss, *res = NULL;
+ unsigned long now = jiffies;
+@@ -374,8 +387,26 @@ struct cfg80211_bss *cfg80211_get_bss(st
+ list_for_each_entry(bss, &dev->bss_list, list) {
+ if ((bss->pub.capability & capa_mask) != capa_val)
+ continue;
+- if (channel && bss->pub.channel != channel)
+- continue;
++ if (channel) {
++ if (bss->pub.channel != channel)
++ continue;
++ if (require_ht != NL80211_CHAN_NO_HT) {
++ struct ieee80211_ht_info *ht_info;
++ ht_info = (struct ieee80211_ht_info *)
++ ieee80211_bss_get_ie(&bss->pub,
++ WLAN_EID_HT_INFORMATION);
++ if (!ht_info)
++ continue;
++ if (require_ht == NL80211_CHAN_HT40MINUS &&
++ !(ht_info->ht_param &
++ IEEE80211_HT_PARAM_CHA_SEC_BELOW))
++ continue;
++ if (require_ht == NL80211_CHAN_HT40PLUS &&
++ !(ht_info->ht_param &
++ IEEE80211_HT_PARAM_CHA_SEC_ABOVE))
++ continue;
++ }
++ }
+ /* Don't get expired BSS structs */
+ if (time_after(now, bss->ts + IEEE80211_SCAN_RESULT_EXPIRE) &&
+ !atomic_read(&bss->hold))
+@@ -392,7 +423,7 @@ struct cfg80211_bss *cfg80211_get_bss(st
+ return NULL;
+ return &res->pub;
+ }
+-EXPORT_SYMBOL(cfg80211_get_bss);
++EXPORT_SYMBOL(cfg80211_get_bss_ht);
+
+ struct cfg80211_bss *cfg80211_get_mesh(struct wiphy *wiphy,
+ struct ieee80211_channel *channel,