From adfeb00e5a06d9ea3eb67564e2ccf2022ffdffe6 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sun, 9 Oct 2011 15:48:03 +0000 Subject: mac80211: update to wireless-testing 2011-10-05 + pending patches SVN-Revision: 28392 --- package/mac80211/patches/310-ibss_ht.patch | 720 ----------------------------- 1 file changed, 720 deletions(-) delete mode 100644 package/mac80211/patches/310-ibss_ht.patch (limited to 'package/mac80211/patches/310-ibss_ht.patch') diff --git a/package/mac80211/patches/310-ibss_ht.patch b/package/mac80211/patches/310-ibss_ht.patch deleted file mode 100644 index 6e0de5b..0000000 --- a/package/mac80211/patches/310-ibss_ht.patch +++ /dev/null @@ -1,720 +0,0 @@ ---- a/include/net/cfg80211.h -+++ b/include/net/cfg80211.h -@@ -1101,6 +1101,7 @@ struct cfg80211_ibss_params { - u8 *ssid; - u8 *bssid; - struct ieee80211_channel *channel; -+ enum nl80211_channel_type channel_type; - u8 *ie; - u8 ssid_len, ie_len; - u16 beacon_interval; -@@ -2612,6 +2613,12 @@ struct cfg80211_bss *cfg80211_get_bss(st - const u8 *bssid, - const u8 *ssid, size_t ssid_len, - u16 capa_mask, u16 capa_val); -+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 channel_type); - static inline struct cfg80211_bss * - cfg80211_get_ibss(struct wiphy *wiphy, - struct ieee80211_channel *channel, ---- 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, ---- a/net/mac80211/ieee80211_i.h -+++ b/net/mac80211/ieee80211_i.h -@@ -465,6 +465,7 @@ struct ieee80211_if_ibss { - u8 ssid_len, ie_len; - u8 *ie; - struct ieee80211_channel *channel; -+ enum nl80211_channel_type channel_type; - - unsigned long ibss_join_req; - /* probe response/beacon for IBSS */ -@@ -1090,6 +1091,7 @@ void ieee80211_ibss_notify_scan_complete - void ieee80211_ibss_setup_sdata(struct ieee80211_sub_if_data *sdata); - struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, - u8 *bssid, u8 *addr, u32 supp_rates, -+ struct ieee80211_ht_cap *ht_cap, - gfp_t gfp); - int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, - struct cfg80211_ibss_params *params); -@@ -1343,6 +1345,12 @@ void ieee80211_recalc_smps(struct ieee80 - size_t ieee80211_ie_split(const u8 *ies, size_t ielen, - const u8 *ids, int n_ids, size_t offset); - size_t ieee80211_ie_split_vendor(const u8 *ies, size_t ielen, size_t offset); -+u8 *ieee80211_ie_build_ht_cap(u8 *pos, struct ieee80211_supported_band *sband, -+ u16 cap); -+u8 *ieee80211_ie_build_ht_info(u8 *pos, -+ struct ieee80211_sta_ht_cap *ht_cap, -+ struct ieee80211_channel *channel, -+ enum nl80211_channel_type channel_type); - - /* internal work items */ - void ieee80211_work_init(struct ieee80211_local *local); -@@ -1371,6 +1379,8 @@ ieee80211_get_channel_mode(struct ieee80 - bool ieee80211_set_channel_type(struct ieee80211_local *local, - struct ieee80211_sub_if_data *sdata, - enum nl80211_channel_type chantype); -+enum nl80211_channel_type ieee80211_ht_info_to_channel_type( -+ struct ieee80211_ht_info *ht_info); - - #ifdef CONFIG_MAC80211_NOINLINE - #define debug_noinline noinline ---- a/net/mac80211/util.c -+++ b/net/mac80211/util.c -@@ -839,23 +839,8 @@ int ieee80211_build_preq_ies(struct ieee - offset = noffset; - } - -- if (sband->ht_cap.ht_supported) { -- u16 cap = sband->ht_cap.cap; -- __le16 tmp; -- -- *pos++ = WLAN_EID_HT_CAPABILITY; -- *pos++ = sizeof(struct ieee80211_ht_cap); -- memset(pos, 0, sizeof(struct ieee80211_ht_cap)); -- tmp = cpu_to_le16(cap); -- memcpy(pos, &tmp, sizeof(u16)); -- pos += sizeof(u16); -- *pos++ = sband->ht_cap.ampdu_factor | -- (sband->ht_cap.ampdu_density << -- IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT); -- memcpy(pos, &sband->ht_cap.mcs, sizeof(sband->ht_cap.mcs)); -- pos += sizeof(sband->ht_cap.mcs); -- pos += 2 + 4 + 1; /* ext info, BF cap, antsel */ -- } -+ if (sband->ht_cap.ht_supported) -+ pos = ieee80211_ie_build_ht_cap(pos, sband, sband->ht_cap.cap); - - /* - * If adding more here, adjust code in main.c -@@ -1378,3 +1363,100 @@ void ieee80211_disable_rssi_reports(stru - _ieee80211_enable_rssi_reports(sdata, 0, 0); - } - EXPORT_SYMBOL(ieee80211_disable_rssi_reports); -+ -+u8 *ieee80211_ie_build_ht_cap(u8 *pos, struct ieee80211_supported_band *sband, -+ u16 cap) -+{ -+ __le16 tmp; -+ -+ *pos++ = WLAN_EID_HT_CAPABILITY; -+ *pos++ = sizeof(struct ieee80211_ht_cap); -+ memset(pos, 0, sizeof(struct ieee80211_ht_cap)); -+ -+ /* capability flags */ -+ tmp = cpu_to_le16(cap); -+ memcpy(pos, &tmp, sizeof(u16)); -+ pos += sizeof(u16); -+ -+ /* AMPDU parameters */ -+ *pos++ = sband->ht_cap.ampdu_factor | -+ (sband->ht_cap.ampdu_density << -+ IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT); -+ -+ /* MCS set */ -+ memcpy(pos, &sband->ht_cap.mcs, sizeof(sband->ht_cap.mcs)); -+ pos += sizeof(sband->ht_cap.mcs); -+ -+ /* extended capabilities */ -+ pos += sizeof(__le16); -+ -+ /* BF capabilities */ -+ pos += sizeof(__le32); -+ -+ /* antenna selection */ -+ pos += sizeof(u8); -+ -+ return pos; -+} -+ -+u8 *ieee80211_ie_build_ht_info(u8 *pos, -+ struct ieee80211_sta_ht_cap *ht_cap, -+ struct ieee80211_channel *channel, -+ enum nl80211_channel_type channel_type) -+{ -+ struct ieee80211_ht_info *ht_info; -+ /* Build HT Information */ -+ *pos++ = WLAN_EID_HT_INFORMATION; -+ *pos++ = sizeof(struct ieee80211_ht_info); -+ ht_info = (struct ieee80211_ht_info *)pos; -+ ht_info->control_chan = -+ ieee80211_frequency_to_channel(channel->center_freq); -+ switch (channel_type) { -+ case NL80211_CHAN_HT40MINUS: -+ ht_info->ht_param = IEEE80211_HT_PARAM_CHA_SEC_BELOW; -+ break; -+ case NL80211_CHAN_HT40PLUS: -+ ht_info->ht_param = IEEE80211_HT_PARAM_CHA_SEC_ABOVE; -+ break; -+ case NL80211_CHAN_HT20: -+ default: -+ ht_info->ht_param = IEEE80211_HT_PARAM_CHA_SEC_NONE; -+ break; -+ } -+ if (ht_cap->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) -+ ht_info->ht_param |= IEEE80211_HT_PARAM_CHAN_WIDTH_ANY; -+ ht_info->operation_mode = 0x0000; -+ ht_info->stbc_param = 0x0000; -+ -+ /* It seems that Basic MCS set and Supported MCS set -+ are identical for the first 10 bytes */ -+ memset(&ht_info->basic_set, 0, 16); -+ memcpy(&ht_info->basic_set, &ht_cap->mcs, 10); -+ -+ return pos + sizeof(struct ieee80211_ht_info); -+} -+ -+enum nl80211_channel_type ieee80211_ht_info_to_channel_type( -+ struct ieee80211_ht_info *ht_info) -+{ -+ enum nl80211_channel_type channel_type; -+ -+ if (!ht_info) -+ return NL80211_CHAN_NO_HT; -+ -+ switch (ht_info->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { -+ case IEEE80211_HT_PARAM_CHA_SEC_NONE: -+ channel_type = NL80211_CHAN_HT20; -+ break; -+ case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: -+ channel_type = NL80211_CHAN_HT40PLUS; -+ break; -+ case IEEE80211_HT_PARAM_CHA_SEC_BELOW: -+ channel_type = NL80211_CHAN_HT40MINUS; -+ break; -+ default: -+ channel_type = NL80211_CHAN_NO_HT; -+ } -+ -+ return channel_type; -+} ---- a/net/mac80211/work.c -+++ b/net/mac80211/work.c -@@ -118,7 +118,6 @@ static void ieee80211_add_ht_ie(struct s - u8 *pos; - u32 flags = channel->flags; - u16 cap = sband->ht_cap.cap; -- __le16 tmp; - - if (!sband->ht_cap.ht_supported) - return; -@@ -169,34 +168,8 @@ static void ieee80211_add_ht_ie(struct s - } - - /* reserve and fill IE */ -- - pos = skb_put(skb, sizeof(struct ieee80211_ht_cap) + 2); -- *pos++ = WLAN_EID_HT_CAPABILITY; -- *pos++ = sizeof(struct ieee80211_ht_cap); -- memset(pos, 0, sizeof(struct ieee80211_ht_cap)); -- -- /* capability flags */ -- tmp = cpu_to_le16(cap); -- memcpy(pos, &tmp, sizeof(u16)); -- pos += sizeof(u16); -- -- /* AMPDU parameters */ -- *pos++ = sband->ht_cap.ampdu_factor | -- (sband->ht_cap.ampdu_density << -- IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT); -- -- /* MCS set */ -- memcpy(pos, &sband->ht_cap.mcs, sizeof(sband->ht_cap.mcs)); -- pos += sizeof(sband->ht_cap.mcs); -- -- /* extended capabilities */ -- pos += sizeof(__le16); -- -- /* BF capabilities */ -- pos += sizeof(__le32); -- -- /* antenna selection */ -- pos += sizeof(u8); -+ ieee80211_ie_build_ht_cap(pos, sband, cap); - } - - static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, ---- a/net/mac80211/agg-tx.c -+++ b/net/mac80211/agg-tx.c -@@ -82,6 +82,8 @@ static void ieee80211_send_addba_request - memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN); - else if (sdata->vif.type == NL80211_IFTYPE_STATION) - memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN); -+ else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) -+ memcpy(mgmt->bssid, sdata->u.ibss.bssid, ETH_ALEN); - - mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | - IEEE80211_STYPE_ACTION); -@@ -399,7 +401,8 @@ int ieee80211_start_tx_ba_session(struct - if (sdata->vif.type != NL80211_IFTYPE_STATION && - sdata->vif.type != NL80211_IFTYPE_AP_VLAN && - sdata->vif.type != NL80211_IFTYPE_AP && -- sdata->vif.type != NL80211_IFTYPE_WDS) -+ sdata->vif.type != NL80211_IFTYPE_WDS && -+ sdata->vif.type != NL80211_IFTYPE_ADHOC) - return -EINVAL; - - if (test_sta_flags(sta, WLAN_STA_BLOCK_BA)) { ---- a/net/mac80211/ht.c -+++ b/net/mac80211/ht.c -@@ -199,6 +199,8 @@ void ieee80211_send_delba(struct ieee802 - memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN); - else if (sdata->vif.type == NL80211_IFTYPE_STATION) - memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN); -+ else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) -+ memcpy(mgmt->bssid, sdata->u.ibss.bssid, ETH_ALEN); - - mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | - IEEE80211_STYPE_ACTION); ---- a/net/mac80211/ibss.c -+++ b/net/mac80211/ibss.c -@@ -35,6 +35,76 @@ - - #define IEEE80211_IBSS_MAX_STA_ENTRIES 128 - -+static bool ieee80211_can_use_ext_chan(struct ieee80211_sub_if_data *sdata, -+ struct ieee80211_channel *channel, -+ enum nl80211_channel_type channel_type) -+{ -+ /* check if we are legally allowed to use HT extension channel */ -+ if ((channel_type == NL80211_CHAN_HT40PLUS) || -+ (channel_type == NL80211_CHAN_HT40MINUS)) { -+ int sec_freq = channel->center_freq + -+ (channel_type == NL80211_CHAN_HT40PLUS ? 20 : -20); -+ struct ieee80211_channel *sec_chan = -+ ieee80211_get_channel(sdata->wdev.wiphy, sec_freq); -+ if (!sec_chan || sec_chan->flags & (IEEE80211_CHAN_DISABLED | -+ IEEE80211_CHAN_PASSIVE_SCAN | -+ IEEE80211_CHAN_NO_IBSS | -+ IEEE80211_CHAN_RADAR)) { -+ return false; -+ } -+ } -+ return true; -+} -+ -+static void ieee80211_update_ht_elems(struct ieee80211_sub_if_data *sdata, -+ struct ieee80211_mgmt *mgmt, -+ struct ieee80211_ht_info *ht_info) -+{ -+ struct ieee80211_local *local = sdata->local; -+ struct ieee80211_supported_band *sband = -+ local->hw.wiphy->bands[local->oper_channel->band]; -+ enum nl80211_channel_type channel_type = -+ ieee80211_ht_info_to_channel_type(ht_info); -+ -+ if (!ieee80211_can_use_ext_chan(sdata, local->oper_channel, channel_type)) -+ channel_type = NL80211_CHAN_HT20; -+ -+ if (channel_type != local->_oper_channel_type) { -+ struct sk_buff *skb = rcu_dereference_protected( -+ sdata->u.ibss.presp, -+ lockdep_is_held(&ifibss->mtx)); -+ struct sk_buff *nskb; -+ u8 *ht_ie; -+ -+ /* update HT IE. If not yet existing, create one */ -+ nskb = skb_copy(skb, GFP_ATOMIC); -+ ht_ie = (u8 *)cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, -+ (const u8 *)(nskb->data + 24 + -+ sizeof(mgmt->u.beacon)), -+ nskb->len - 24 - -+ sizeof(mgmt->u.beacon)); -+ if (!ht_ie) -+ ht_ie = skb_put(nskb, 4 + -+ sizeof(struct ieee80211_ht_cap) + -+ sizeof(struct ieee80211_ht_info)); -+ -+ ht_ie = ieee80211_ie_build_ht_cap(ht_ie, sband, -+ sband->ht_cap.cap); -+ ht_ie = ieee80211_ie_build_ht_info(ht_ie, &sband->ht_cap, -+ local->oper_channel, channel_type); -+ rcu_assign_pointer(sdata->u.ibss.presp, nskb); -+ kfree_skb(skb); -+ -+ if(!ieee80211_set_channel_type(local, sdata, channel_type)) { -+ channel_type = NL80211_CHAN_HT20; -+ WARN_ON(!ieee80211_set_channel_type(local, sdata, -+ channel_type)); -+ } -+ -+ ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); -+ } -+ -+} - - static void ieee80211_rx_mgmt_auth_ibss(struct ieee80211_sub_if_data *sdata, - struct ieee80211_mgmt *mgmt, -@@ -64,6 +134,7 @@ static void ieee80211_rx_mgmt_auth_ibss( - static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, - const u8 *bssid, const int beacon_int, - struct ieee80211_channel *chan, -+ enum nl80211_channel_type channel_type, - const u32 basic_rates, - const u16 capability, u64 tsf) - { -@@ -104,8 +175,17 @@ static void __ieee80211_sta_join_ibss(st - - sdata->drop_unencrypted = capability & WLAN_CAPABILITY_PRIVACY ? 1 : 0; - -+ /* entering a legacy IBSS. Use given HT configuration. */ -+ if (channel_type == NL80211_CHAN_NO_HT) -+ channel_type = ifibss->channel_type; - local->oper_channel = chan; -- WARN_ON(!ieee80211_set_channel_type(local, sdata, NL80211_CHAN_NO_HT)); -+ -+ /* if phy is on a different extension channel, setting ht40 will fail */ -+ if (!ieee80211_set_channel_type(local, sdata, channel_type)) { -+ channel_type = NL80211_CHAN_HT20; -+ WARN_ON(!ieee80211_set_channel_type(local, sdata, -+ channel_type)); -+ } - ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); - - sband = local->hw.wiphy->bands[chan->band]; -@@ -171,6 +251,18 @@ static void __ieee80211_sta_join_ibss(st - memcpy(skb_put(skb, ifibss->ie_len), - ifibss->ie, ifibss->ie_len); - -+ /* add HT capability and information IEs */ -+ if (channel_type != NL80211_CHAN_NO_HT && sband->ht_cap.ht_supported) { -+ pos = skb_put(skb, 4 + -+ sizeof(struct ieee80211_ht_cap) + -+ sizeof(struct ieee80211_ht_info)); -+ pos = ieee80211_ie_build_ht_cap(pos, sband, sband->ht_cap.cap); -+ pos = ieee80211_ie_build_ht_info(pos, -+ &sband->ht_cap, -+ chan, -+ channel_type); -+ } -+ - if (local->hw.queues >= 4) { - pos = skb_put(skb, 9); - *pos++ = WLAN_EID_VENDOR_SPECIFIC; -@@ -219,6 +311,8 @@ static void ieee80211_sta_join_ibss(stru - u32 basic_rates; - int i, j; - u16 beacon_int = cbss->beacon_interval; -+ const u8 *ht_info_ie; -+ enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT; - - lockdep_assert_held(&sdata->u.ibss.mtx); - -@@ -242,9 +336,23 @@ static void ieee80211_sta_join_ibss(stru - } - } - -+ ht_info_ie = ieee80211_bss_get_ie(cbss, WLAN_EID_HT_INFORMATION); -+ if (ht_info_ie) -+ channel_type = ieee80211_ht_info_to_channel_type( -+ (struct ieee80211_ht_info *) (ht_info_ie + 2)); -+ -+ if (!ieee80211_can_use_ext_chan(sdata, cbss->channel, channel_type)) { -+ channel_type = NL80211_CHAN_HT20; -+#ifdef CONFIG_MAC80211_IBSS_DEBUG -+ printk(KERN_DEBUG "%s: IBSS not allowed on secondary channel\n", -+ sdata->name); -+#endif -+ } -+ - __ieee80211_sta_join_ibss(sdata, cbss->bssid, - beacon_int, - cbss->channel, -+ channel_type, - basic_rates, - cbss->capability, - cbss->tsf); -@@ -310,11 +418,24 @@ static void ieee80211_rx_bss_info(struct - } else - sta = ieee80211_ibss_add_sta(sdata, mgmt->bssid, - mgmt->sa, supp_rates, -- GFP_ATOMIC); -+ elems->ht_cap_elem, GFP_ATOMIC); - } - -- if (sta && elems->wmm_info) -- set_sta_flags(sta, WLAN_STA_WME); -+ if (sta) { -+ if (elems->wmm_info) -+ set_sta_flags(sta, WLAN_STA_WME); -+ -+ /* remote station uses ht */ -+ if (elems->ht_info_elem) { -+ ieee80211_update_ht_elems(sdata, mgmt, -+ elems->ht_info_elem); -+ ieee80211_ht_cap_ie_to_sta_ht_cap( -+ local->hw.wiphy->bands[ -+ local->oper_channel->band], -+ elems->ht_cap_elem, -+ &sta->sta.ht_cap); -+ } -+ } - - rcu_read_unlock(); - } -@@ -404,7 +525,7 @@ static void ieee80211_rx_bss_info(struct - ieee80211_sta_join_ibss(sdata, bss); - supp_rates = ieee80211_sta_get_rates(local, elems, band); - ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa, -- supp_rates, GFP_KERNEL); -+ supp_rates, elems->ht_cap_elem, GFP_KERNEL); - } - - put_bss: -@@ -417,7 +538,8 @@ static void ieee80211_rx_bss_info(struct - * must be callable in atomic context. - */ - struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, -- u8 *bssid,u8 *addr, u32 supp_rates, -+ u8 *bssid, u8 *addr, u32 supp_rates, -+ struct ieee80211_ht_cap *ht_cap, - gfp_t gfp) - { - struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; -@@ -458,6 +580,11 @@ struct sta_info *ieee80211_ibss_add_sta( - sta->sta.supp_rates[band] = supp_rates | - ieee80211_mandatory_rates(local, band); - -+ /* fill in ht rates */ -+ if (ht_cap) -+ ieee80211_ht_cap_ie_to_sta_ht_cap(local->hw.wiphy->bands[band], -+ ht_cap, &sta->sta.ht_cap); -+ - rate_control_rate_init(sta); - - /* If it fails, maybe we raced another insertion? */ -@@ -556,8 +683,8 @@ static void ieee80211_sta_create_ibss(st - sdata->drop_unencrypted = 0; - - __ieee80211_sta_join_ibss(sdata, bssid, sdata->vif.bss_conf.beacon_int, -- ifibss->channel, ifibss->basic_rates, -- capability, 0); -+ ifibss->channel, ifibss->channel_type, -+ ifibss->basic_rates, capability, 0); - } - - /* -@@ -594,10 +721,10 @@ static void ieee80211_sta_find_ibss(stru - chan = ifibss->channel; - if (!is_zero_ether_addr(ifibss->bssid)) - bssid = ifibss->bssid; -- cbss = cfg80211_get_bss(local->hw.wiphy, chan, bssid, -+ cbss = cfg80211_get_bss_ht(local->hw.wiphy, chan, bssid, - ifibss->ssid, ifibss->ssid_len, - WLAN_CAPABILITY_IBSS | WLAN_CAPABILITY_PRIVACY, -- capability); -+ capability, ifibss->channel_type); - - if (cbss) { - struct ieee80211_bss *bss; -@@ -896,10 +1023,15 @@ int ieee80211_ibss_join(struct ieee80211 - struct sk_buff *skb; - - skb = dev_alloc_skb(sdata->local->hw.extra_tx_headroom + -- 36 /* bitrates */ + -- 34 /* SSID */ + -- 3 /* DS params */ + -- 4 /* IBSS params */ + -+ sizeof(struct ieee80211_hdr_3addr) + -+ 12 /* struct ieee80211_mgmt.u.beacon */ + -+ 2 + IEEE80211_MAX_SSID_LEN /* max SSID */ + -+ 2 + 8 /* max Supported Rates */ + -+ 3 /* max DS params */ + -+ 4 /* IBSS params */ + -+ 2 + (IEEE80211_MAX_SUPP_RATES - 8) + -+ 2 + sizeof(struct ieee80211_ht_cap) + -+ 2 + sizeof(struct ieee80211_ht_info) + - params->ie_len); - if (!skb) - return -ENOMEM; -@@ -920,13 +1052,15 @@ int ieee80211_ibss_join(struct ieee80211 - sdata->vif.bss_conf.beacon_int = params->beacon_interval; - - sdata->u.ibss.channel = params->channel; -+ sdata->u.ibss.channel_type = params->channel_type; - sdata->u.ibss.fixed_channel = params->channel_fixed; - - /* fix ourselves to that channel now already */ - if (params->channel_fixed) { - sdata->local->oper_channel = params->channel; -- WARN_ON(!ieee80211_set_channel_type(sdata->local, sdata, -- NL80211_CHAN_NO_HT)); -+ if(!ieee80211_set_channel_type(sdata->local, sdata, -+ params->channel_type)) -+ return -EINVAL; - } - - if (params->ie) { ---- a/net/mac80211/rx.c -+++ b/net/mac80211/rx.c -@@ -2164,7 +2164,8 @@ ieee80211_rx_h_action(struct ieee80211_r - if (sdata->vif.type != NL80211_IFTYPE_STATION && - sdata->vif.type != NL80211_IFTYPE_AP_VLAN && - sdata->vif.type != NL80211_IFTYPE_AP && -- sdata->vif.type != NL80211_IFTYPE_WDS) -+ sdata->vif.type != NL80211_IFTYPE_WDS && -+ sdata->vif.type != NL80211_IFTYPE_ADHOC) - break; - - /* verify action_code is present */ -@@ -2699,7 +2700,8 @@ static int prepare_for_handlers(struct i - else - rate_idx = status->rate_idx; - rx->sta = ieee80211_ibss_add_sta(sdata, bssid, -- hdr->addr2, BIT(rate_idx), GFP_ATOMIC); -+ hdr->addr2, BIT(rate_idx), NULL, -+ GFP_ATOMIC); - } - break; - case NL80211_IFTYPE_MESH_POINT: ---- a/net/mac80211/agg-rx.c -+++ b/net/mac80211/agg-rx.c -@@ -182,6 +182,8 @@ static void ieee80211_send_addba_resp(st - memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN); - else if (sdata->vif.type == NL80211_IFTYPE_WDS) - memcpy(mgmt->bssid, da, ETH_ALEN); -+ else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) -+ memcpy(mgmt->bssid, sdata->u.ibss.bssid, ETH_ALEN); - - mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | - IEEE80211_STYPE_ACTION); -- cgit v1.1