1 --- a/include/net/cfg80211.h
2 +++ b/include/net/cfg80211.h
3 @@ -1085,6 +1085,7 @@ struct cfg80211_ibss_params {
6 struct ieee80211_channel *channel;
7 + enum nl80211_channel_type channel_type;
11 @@ -2584,6 +2585,12 @@ struct cfg80211_bss *cfg80211_get_bss(st
13 const u8 *ssid, size_t ssid_len,
14 u16 capa_mask, u16 capa_val);
15 +struct cfg80211_bss *cfg80211_get_bss_ht(struct wiphy *wiphy,
16 + struct ieee80211_channel *channel,
18 + const u8 *ssid, size_t ssid_len,
19 + u16 capa_mask, u16 capa_val,
20 + enum nl80211_channel_type channel_type);
21 static inline struct cfg80211_bss *
22 cfg80211_get_ibss(struct wiphy *wiphy,
23 struct ieee80211_channel *channel,
24 --- a/net/wireless/nl80211.c
25 +++ b/net/wireless/nl80211.c
26 @@ -4470,13 +4470,41 @@ static int nl80211_join_ibss(struct sk_b
27 ibss.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
30 - ibss.channel = ieee80211_get_channel(wiphy,
31 - nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]));
32 + if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) {
33 + enum nl80211_channel_type channel_type;
35 + channel_type = nla_get_u32(
36 + info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]);
37 + if (channel_type != NL80211_CHAN_NO_HT &&
38 + channel_type != NL80211_CHAN_HT20 &&
39 + channel_type != NL80211_CHAN_HT40PLUS &&
40 + channel_type != NL80211_CHAN_HT40MINUS)
42 + ibss.channel_type = channel_type;
44 + ibss.channel_type = NL80211_CHAN_NO_HT;
47 + ibss.channel = rdev_freq_to_chan(rdev,
48 + nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]),
51 + ibss.channel->flags & IEEE80211_CHAN_PASSIVE_SCAN ||
52 ibss.channel->flags & IEEE80211_CHAN_NO_IBSS ||
53 - ibss.channel->flags & IEEE80211_CHAN_DISABLED)
54 + ibss.channel->flags & IEEE80211_CHAN_RADAR)
57 + /* Both channels should be able to initiate communication */
58 + if ((ibss.channel_type == NL80211_CHAN_HT40PLUS ||
59 + ibss.channel_type == NL80211_CHAN_HT40MINUS) &&
60 + !can_beacon_sec_chan(&rdev->wiphy, ibss.channel,
61 + ibss.channel_type)) {
63 + "cfg80211: Secondary channel not "
64 + "allowed to initiate communication\n");
68 ibss.channel_fixed = !!info->attrs[NL80211_ATTR_FREQ_FIXED];
69 ibss.privacy = !!info->attrs[NL80211_ATTR_PRIVACY];
71 --- a/net/wireless/chan.c
72 +++ b/net/wireless/chan.c
73 @@ -44,7 +44,7 @@ rdev_freq_to_chan(struct cfg80211_regist
77 -static bool can_beacon_sec_chan(struct wiphy *wiphy,
78 +bool can_beacon_sec_chan(struct wiphy *wiphy,
79 struct ieee80211_channel *chan,
80 enum nl80211_channel_type channel_type)
82 @@ -75,6 +75,7 @@ static bool can_beacon_sec_chan(struct w
86 +EXPORT_SYMBOL(can_beacon_sec_chan);
88 int cfg80211_set_freq(struct cfg80211_registered_device *rdev,
89 struct wireless_dev *wdev, int freq,
90 --- a/net/wireless/core.h
91 +++ b/net/wireless/core.h
92 @@ -441,6 +441,9 @@ cfg80211_can_add_interface(struct cfg802
93 struct ieee80211_channel *
94 rdev_freq_to_chan(struct cfg80211_registered_device *rdev,
95 int freq, enum nl80211_channel_type channel_type);
96 +bool can_beacon_sec_chan(struct wiphy *wiphy,
97 + struct ieee80211_channel *chan,
98 + enum nl80211_channel_type channel_type);
99 int cfg80211_set_freq(struct cfg80211_registered_device *rdev,
100 struct wireless_dev *wdev, int freq,
101 enum nl80211_channel_type channel_type);
102 --- a/net/wireless/scan.c
103 +++ b/net/wireless/scan.c
104 @@ -365,6 +365,19 @@ struct cfg80211_bss *cfg80211_get_bss(st
105 const u8 *ssid, size_t ssid_len,
106 u16 capa_mask, u16 capa_val)
108 + /* call HT version with no HT requirements */
109 + return cfg80211_get_bss_ht(wiphy, channel, bssid, ssid, ssid_len,
110 + capa_mask, capa_val, NL80211_CHAN_NO_HT);
112 +EXPORT_SYMBOL(cfg80211_get_bss);
114 +struct cfg80211_bss *cfg80211_get_bss_ht(struct wiphy *wiphy,
115 + struct ieee80211_channel *channel,
117 + const u8 *ssid, size_t ssid_len,
118 + u16 capa_mask, u16 capa_val,
119 + enum nl80211_channel_type require_ht)
121 struct cfg80211_registered_device *dev = wiphy_to_dev(wiphy);
122 struct cfg80211_internal_bss *bss, *res = NULL;
123 unsigned long now = jiffies;
124 @@ -374,8 +387,26 @@ struct cfg80211_bss *cfg80211_get_bss(st
125 list_for_each_entry(bss, &dev->bss_list, list) {
126 if ((bss->pub.capability & capa_mask) != capa_val)
128 - if (channel && bss->pub.channel != channel)
131 + if (bss->pub.channel != channel)
133 + if (require_ht != NL80211_CHAN_NO_HT) {
134 + struct ieee80211_ht_info *ht_info;
135 + ht_info = (struct ieee80211_ht_info *)
136 + ieee80211_bss_get_ie(&bss->pub,
137 + WLAN_EID_HT_INFORMATION);
140 + if (require_ht == NL80211_CHAN_HT40MINUS &&
141 + !(ht_info->ht_param &
142 + IEEE80211_HT_PARAM_CHA_SEC_BELOW))
144 + if (require_ht == NL80211_CHAN_HT40PLUS &&
145 + !(ht_info->ht_param &
146 + IEEE80211_HT_PARAM_CHA_SEC_ABOVE))
150 /* Don't get expired BSS structs */
151 if (time_after(now, bss->ts + IEEE80211_SCAN_RESULT_EXPIRE) &&
152 !atomic_read(&bss->hold))
153 @@ -392,7 +423,7 @@ struct cfg80211_bss *cfg80211_get_bss(st
157 -EXPORT_SYMBOL(cfg80211_get_bss);
158 +EXPORT_SYMBOL(cfg80211_get_bss_ht);
160 struct cfg80211_bss *cfg80211_get_mesh(struct wiphy *wiphy,
161 struct ieee80211_channel *channel,
162 --- a/net/mac80211/ieee80211_i.h
163 +++ b/net/mac80211/ieee80211_i.h
164 @@ -464,6 +464,7 @@ struct ieee80211_if_ibss {
167 struct ieee80211_channel *channel;
168 + enum nl80211_channel_type channel_type;
170 unsigned long ibss_join_req;
171 /* probe response/beacon for IBSS */
172 @@ -1089,6 +1090,7 @@ void ieee80211_ibss_notify_scan_complete
173 void ieee80211_ibss_setup_sdata(struct ieee80211_sub_if_data *sdata);
174 struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata,
175 u8 *bssid, u8 *addr, u32 supp_rates,
176 + struct ieee80211_ht_cap *ht_cap,
178 int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,
179 struct cfg80211_ibss_params *params);
180 @@ -1343,6 +1345,12 @@ void ieee80211_recalc_smps(struct ieee80
181 size_t ieee80211_ie_split(const u8 *ies, size_t ielen,
182 const u8 *ids, int n_ids, size_t offset);
183 size_t ieee80211_ie_split_vendor(const u8 *ies, size_t ielen, size_t offset);
184 +u8 *ieee80211_ie_build_ht_cap(u8 *pos, struct ieee80211_supported_band *sband,
186 +u8 *ieee80211_ie_build_ht_info(u8 *pos,
187 + struct ieee80211_sta_ht_cap *ht_cap,
188 + struct ieee80211_channel *channel,
189 + enum nl80211_channel_type channel_type);
191 /* internal work items */
192 void ieee80211_work_init(struct ieee80211_local *local);
193 @@ -1371,6 +1379,8 @@ ieee80211_get_channel_mode(struct ieee80
194 bool ieee80211_set_channel_type(struct ieee80211_local *local,
195 struct ieee80211_sub_if_data *sdata,
196 enum nl80211_channel_type chantype);
197 +enum nl80211_channel_type ieee80211_ht_info_to_channel_type(
198 + struct ieee80211_ht_info *ht_info);
200 #ifdef CONFIG_MAC80211_NOINLINE
201 #define debug_noinline noinline
202 --- a/net/mac80211/util.c
203 +++ b/net/mac80211/util.c
204 @@ -841,23 +841,8 @@ int ieee80211_build_preq_ies(struct ieee
208 - if (sband->ht_cap.ht_supported) {
209 - u16 cap = sband->ht_cap.cap;
212 - *pos++ = WLAN_EID_HT_CAPABILITY;
213 - *pos++ = sizeof(struct ieee80211_ht_cap);
214 - memset(pos, 0, sizeof(struct ieee80211_ht_cap));
215 - tmp = cpu_to_le16(cap);
216 - memcpy(pos, &tmp, sizeof(u16));
217 - pos += sizeof(u16);
218 - *pos++ = sband->ht_cap.ampdu_factor |
219 - (sband->ht_cap.ampdu_density <<
220 - IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT);
221 - memcpy(pos, &sband->ht_cap.mcs, sizeof(sband->ht_cap.mcs));
222 - pos += sizeof(sband->ht_cap.mcs);
223 - pos += 2 + 4 + 1; /* ext info, BF cap, antsel */
225 + if (sband->ht_cap.ht_supported)
226 + pos = ieee80211_ie_build_ht_cap(pos, sband, sband->ht_cap.cap);
229 * If adding more here, adjust code in main.c
230 @@ -1381,3 +1366,100 @@ void ieee80211_disable_rssi_reports(stru
231 _ieee80211_enable_rssi_reports(sdata, 0, 0);
233 EXPORT_SYMBOL(ieee80211_disable_rssi_reports);
235 +u8 *ieee80211_ie_build_ht_cap(u8 *pos, struct ieee80211_supported_band *sband,
240 + *pos++ = WLAN_EID_HT_CAPABILITY;
241 + *pos++ = sizeof(struct ieee80211_ht_cap);
242 + memset(pos, 0, sizeof(struct ieee80211_ht_cap));
244 + /* capability flags */
245 + tmp = cpu_to_le16(cap);
246 + memcpy(pos, &tmp, sizeof(u16));
247 + pos += sizeof(u16);
249 + /* AMPDU parameters */
250 + *pos++ = sband->ht_cap.ampdu_factor |
251 + (sband->ht_cap.ampdu_density <<
252 + IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT);
255 + memcpy(pos, &sband->ht_cap.mcs, sizeof(sband->ht_cap.mcs));
256 + pos += sizeof(sband->ht_cap.mcs);
258 + /* extended capabilities */
259 + pos += sizeof(__le16);
261 + /* BF capabilities */
262 + pos += sizeof(__le32);
264 + /* antenna selection */
270 +u8 *ieee80211_ie_build_ht_info(u8 *pos,
271 + struct ieee80211_sta_ht_cap *ht_cap,
272 + struct ieee80211_channel *channel,
273 + enum nl80211_channel_type channel_type)
275 + struct ieee80211_ht_info *ht_info;
276 + /* Build HT Information */
277 + *pos++ = WLAN_EID_HT_INFORMATION;
278 + *pos++ = sizeof(struct ieee80211_ht_info);
279 + ht_info = (struct ieee80211_ht_info *)pos;
280 + ht_info->control_chan =
281 + ieee80211_frequency_to_channel(channel->center_freq);
282 + switch (channel_type) {
283 + case NL80211_CHAN_HT40MINUS:
284 + ht_info->ht_param = IEEE80211_HT_PARAM_CHA_SEC_BELOW;
286 + case NL80211_CHAN_HT40PLUS:
287 + ht_info->ht_param = IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
289 + case NL80211_CHAN_HT20:
291 + ht_info->ht_param = IEEE80211_HT_PARAM_CHA_SEC_NONE;
294 + if (ht_cap->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40)
295 + ht_info->ht_param |= IEEE80211_HT_PARAM_CHAN_WIDTH_ANY;
296 + ht_info->operation_mode = 0x0000;
297 + ht_info->stbc_param = 0x0000;
299 + /* It seems that Basic MCS set and Supported MCS set
300 + are identical for the first 10 bytes */
301 + memset(&ht_info->basic_set, 0, 16);
302 + memcpy(&ht_info->basic_set, &ht_cap->mcs, 10);
304 + return pos + sizeof(struct ieee80211_ht_info);
307 +enum nl80211_channel_type ieee80211_ht_info_to_channel_type(
308 + struct ieee80211_ht_info *ht_info)
310 + enum nl80211_channel_type channel_type;
313 + return NL80211_CHAN_NO_HT;
315 + switch (ht_info->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) {
316 + case IEEE80211_HT_PARAM_CHA_SEC_NONE:
317 + channel_type = NL80211_CHAN_HT20;
319 + case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
320 + channel_type = NL80211_CHAN_HT40PLUS;
322 + case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
323 + channel_type = NL80211_CHAN_HT40MINUS;
326 + channel_type = NL80211_CHAN_NO_HT;
329 + return channel_type;
331 --- a/net/mac80211/work.c
332 +++ b/net/mac80211/work.c
333 @@ -118,7 +118,6 @@ static void ieee80211_add_ht_ie(struct s
335 u32 flags = channel->flags;
336 u16 cap = sband->ht_cap.cap;
339 if (!sband->ht_cap.ht_supported)
341 @@ -169,34 +168,8 @@ static void ieee80211_add_ht_ie(struct s
344 /* reserve and fill IE */
346 pos = skb_put(skb, sizeof(struct ieee80211_ht_cap) + 2);
347 - *pos++ = WLAN_EID_HT_CAPABILITY;
348 - *pos++ = sizeof(struct ieee80211_ht_cap);
349 - memset(pos, 0, sizeof(struct ieee80211_ht_cap));
351 - /* capability flags */
352 - tmp = cpu_to_le16(cap);
353 - memcpy(pos, &tmp, sizeof(u16));
354 - pos += sizeof(u16);
356 - /* AMPDU parameters */
357 - *pos++ = sband->ht_cap.ampdu_factor |
358 - (sband->ht_cap.ampdu_density <<
359 - IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT);
362 - memcpy(pos, &sband->ht_cap.mcs, sizeof(sband->ht_cap.mcs));
363 - pos += sizeof(sband->ht_cap.mcs);
365 - /* extended capabilities */
366 - pos += sizeof(__le16);
368 - /* BF capabilities */
369 - pos += sizeof(__le32);
371 - /* antenna selection */
373 + ieee80211_ie_build_ht_cap(pos, sband, cap);
376 static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata,
377 --- a/net/mac80211/agg-tx.c
378 +++ b/net/mac80211/agg-tx.c
379 @@ -84,6 +84,8 @@ static void ieee80211_send_addba_request
380 memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN);
381 else if (sdata->vif.type == NL80211_IFTYPE_STATION)
382 memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN);
383 + else if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
384 + memcpy(mgmt->bssid, sdata->u.ibss.bssid, ETH_ALEN);
386 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
387 IEEE80211_STYPE_ACTION);
388 @@ -400,7 +402,8 @@ int ieee80211_start_tx_ba_session(struct
389 if (sdata->vif.type != NL80211_IFTYPE_STATION &&
390 sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
391 sdata->vif.type != NL80211_IFTYPE_AP &&
392 - sdata->vif.type != NL80211_IFTYPE_WDS)
393 + sdata->vif.type != NL80211_IFTYPE_WDS &&
394 + sdata->vif.type != NL80211_IFTYPE_ADHOC)
397 if (test_sta_flags(sta, WLAN_STA_BLOCK_BA)) {
398 --- a/net/mac80211/ht.c
399 +++ b/net/mac80211/ht.c
400 @@ -203,6 +203,8 @@ void ieee80211_send_delba(struct ieee802
401 memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN);
402 else if (sdata->vif.type == NL80211_IFTYPE_STATION)
403 memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN);
404 + else if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
405 + memcpy(mgmt->bssid, sdata->u.ibss.bssid, ETH_ALEN);
407 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
408 IEEE80211_STYPE_ACTION);
409 --- a/net/mac80211/ibss.c
410 +++ b/net/mac80211/ibss.c
413 #define IEEE80211_IBSS_MAX_STA_ENTRIES 128
415 +static bool ieee80211_can_use_ext_chan(struct ieee80211_sub_if_data *sdata,
416 + struct ieee80211_channel *channel,
417 + enum nl80211_channel_type channel_type)
419 + /* check if we are legally allowed to use HT extension channel */
420 + if ((channel_type == NL80211_CHAN_HT40PLUS) ||
421 + (channel_type == NL80211_CHAN_HT40MINUS)) {
422 + int sec_freq = channel->center_freq +
423 + (channel_type == NL80211_CHAN_HT40PLUS ? 20 : -20);
424 + struct ieee80211_channel *sec_chan =
425 + ieee80211_get_channel(sdata->wdev.wiphy, sec_freq);
426 + if (!sec_chan || sec_chan->flags & (IEEE80211_CHAN_DISABLED |
427 + IEEE80211_CHAN_PASSIVE_SCAN |
428 + IEEE80211_CHAN_NO_IBSS |
429 + IEEE80211_CHAN_RADAR)) {
436 +static void ieee80211_update_ht_elems(struct ieee80211_sub_if_data *sdata,
437 + struct ieee80211_mgmt *mgmt,
438 + struct ieee80211_ht_info *ht_info)
440 + struct ieee80211_local *local = sdata->local;
441 + struct ieee80211_supported_band *sband =
442 + local->hw.wiphy->bands[local->oper_channel->band];
443 + enum nl80211_channel_type channel_type =
444 + ieee80211_ht_info_to_channel_type(ht_info);
446 + if (!ieee80211_can_use_ext_chan(sdata, local->oper_channel, channel_type))
447 + channel_type = NL80211_CHAN_HT20;
449 + if (channel_type != local->_oper_channel_type) {
450 + struct sk_buff *skb = rcu_dereference_protected(
451 + sdata->u.ibss.presp,
452 + lockdep_is_held(&ifibss->mtx));
453 + struct sk_buff *nskb;
456 + /* update HT IE. If not yet existing, create one */
457 + nskb = skb_copy(skb, GFP_ATOMIC);
458 + ht_ie = (u8 *)cfg80211_find_ie(WLAN_EID_HT_CAPABILITY,
459 + (const u8 *)(nskb->data + 24 +
460 + sizeof(mgmt->u.beacon)),
462 + sizeof(mgmt->u.beacon));
464 + ht_ie = skb_put(nskb, 4 +
465 + sizeof(struct ieee80211_ht_cap) +
466 + sizeof(struct ieee80211_ht_info));
468 + ht_ie = ieee80211_ie_build_ht_cap(ht_ie, sband,
469 + sband->ht_cap.cap);
470 + ht_ie = ieee80211_ie_build_ht_info(ht_ie, &sband->ht_cap,
471 + local->oper_channel, channel_type);
472 + rcu_assign_pointer(sdata->u.ibss.presp, nskb);
475 + if(!ieee80211_set_channel_type(local, sdata, channel_type)) {
476 + channel_type = NL80211_CHAN_HT20;
477 + WARN_ON(!ieee80211_set_channel_type(local, sdata,
481 + ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
486 static void ieee80211_rx_mgmt_auth_ibss(struct ieee80211_sub_if_data *sdata,
487 struct ieee80211_mgmt *mgmt,
488 @@ -64,6 +134,7 @@ static void ieee80211_rx_mgmt_auth_ibss(
489 static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
490 const u8 *bssid, const int beacon_int,
491 struct ieee80211_channel *chan,
492 + enum nl80211_channel_type channel_type,
493 const u32 basic_rates,
494 const u16 capability, u64 tsf)
496 @@ -104,8 +175,17 @@ static void __ieee80211_sta_join_ibss(st
498 sdata->drop_unencrypted = capability & WLAN_CAPABILITY_PRIVACY ? 1 : 0;
500 + /* entering a legacy IBSS. Use given HT configuration. */
501 + if (channel_type == NL80211_CHAN_NO_HT)
502 + channel_type = ifibss->channel_type;
503 local->oper_channel = chan;
504 - WARN_ON(!ieee80211_set_channel_type(local, sdata, NL80211_CHAN_NO_HT));
506 + /* if phy is on a different extension channel, setting ht40 will fail */
507 + if (!ieee80211_set_channel_type(local, sdata, channel_type)) {
508 + channel_type = NL80211_CHAN_HT20;
509 + WARN_ON(!ieee80211_set_channel_type(local, sdata,
512 ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
514 sband = local->hw.wiphy->bands[chan->band];
515 @@ -171,6 +251,18 @@ static void __ieee80211_sta_join_ibss(st
516 memcpy(skb_put(skb, ifibss->ie_len),
517 ifibss->ie, ifibss->ie_len);
519 + /* add HT capability and information IEs */
520 + if (channel_type != NL80211_CHAN_NO_HT && sband->ht_cap.ht_supported) {
521 + pos = skb_put(skb, 4 +
522 + sizeof(struct ieee80211_ht_cap) +
523 + sizeof(struct ieee80211_ht_info));
524 + pos = ieee80211_ie_build_ht_cap(pos, sband, sband->ht_cap.cap);
525 + pos = ieee80211_ie_build_ht_info(pos,
531 if (local->hw.queues >= 4) {
532 pos = skb_put(skb, 9);
533 *pos++ = WLAN_EID_VENDOR_SPECIFIC;
534 @@ -219,6 +311,8 @@ static void ieee80211_sta_join_ibss(stru
537 u16 beacon_int = cbss->beacon_interval;
538 + const u8 *ht_info_ie;
539 + enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT;
541 lockdep_assert_held(&sdata->u.ibss.mtx);
543 @@ -242,9 +336,23 @@ static void ieee80211_sta_join_ibss(stru
547 + ht_info_ie = ieee80211_bss_get_ie(cbss, WLAN_EID_HT_INFORMATION);
549 + channel_type = ieee80211_ht_info_to_channel_type(
550 + (struct ieee80211_ht_info *) (ht_info_ie + 2));
552 + if (!ieee80211_can_use_ext_chan(sdata, cbss->channel, channel_type)) {
553 + channel_type = NL80211_CHAN_HT20;
554 +#ifdef CONFIG_MAC80211_IBSS_DEBUG
555 + printk(KERN_DEBUG "%s: IBSS not allowed on secondary channel\n",
560 __ieee80211_sta_join_ibss(sdata, cbss->bssid,
567 @@ -310,11 +418,24 @@ static void ieee80211_rx_bss_info(struct
569 sta = ieee80211_ibss_add_sta(sdata, mgmt->bssid,
570 mgmt->sa, supp_rates,
572 + elems->ht_cap_elem, GFP_ATOMIC);
575 - if (sta && elems->wmm_info)
576 - set_sta_flags(sta, WLAN_STA_WME);
578 + if (elems->wmm_info)
579 + set_sta_flags(sta, WLAN_STA_WME);
581 + /* remote station uses ht */
582 + if (elems->ht_info_elem) {
583 + ieee80211_update_ht_elems(sdata, mgmt,
584 + elems->ht_info_elem);
585 + ieee80211_ht_cap_ie_to_sta_ht_cap(
586 + local->hw.wiphy->bands[
587 + local->oper_channel->band],
588 + elems->ht_cap_elem,
595 @@ -404,7 +525,7 @@ static void ieee80211_rx_bss_info(struct
596 ieee80211_sta_join_ibss(sdata, bss);
597 supp_rates = ieee80211_sta_get_rates(local, elems, band);
598 ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa,
599 - supp_rates, GFP_KERNEL);
600 + supp_rates, elems->ht_cap_elem, GFP_KERNEL);
604 @@ -417,7 +538,8 @@ static void ieee80211_rx_bss_info(struct
605 * must be callable in atomic context.
607 struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata,
608 - u8 *bssid,u8 *addr, u32 supp_rates,
609 + u8 *bssid, u8 *addr, u32 supp_rates,
610 + struct ieee80211_ht_cap *ht_cap,
613 struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
614 @@ -458,6 +580,11 @@ struct sta_info *ieee80211_ibss_add_sta(
615 sta->sta.supp_rates[band] = supp_rates |
616 ieee80211_mandatory_rates(local, band);
618 + /* fill in ht rates */
620 + ieee80211_ht_cap_ie_to_sta_ht_cap(local->hw.wiphy->bands[band],
621 + ht_cap, &sta->sta.ht_cap);
623 rate_control_rate_init(sta);
625 /* If it fails, maybe we raced another insertion? */
626 @@ -556,8 +683,8 @@ static void ieee80211_sta_create_ibss(st
627 sdata->drop_unencrypted = 0;
629 __ieee80211_sta_join_ibss(sdata, bssid, sdata->vif.bss_conf.beacon_int,
630 - ifibss->channel, ifibss->basic_rates,
632 + ifibss->channel, ifibss->channel_type,
633 + ifibss->basic_rates, capability, 0);
637 @@ -594,10 +721,10 @@ static void ieee80211_sta_find_ibss(stru
638 chan = ifibss->channel;
639 if (!is_zero_ether_addr(ifibss->bssid))
640 bssid = ifibss->bssid;
641 - cbss = cfg80211_get_bss(local->hw.wiphy, chan, bssid,
642 + cbss = cfg80211_get_bss_ht(local->hw.wiphy, chan, bssid,
643 ifibss->ssid, ifibss->ssid_len,
644 WLAN_CAPABILITY_IBSS | WLAN_CAPABILITY_PRIVACY,
646 + capability, ifibss->channel_type);
649 struct ieee80211_bss *bss;
650 @@ -896,10 +1023,15 @@ int ieee80211_ibss_join(struct ieee80211
653 skb = dev_alloc_skb(sdata->local->hw.extra_tx_headroom +
654 - 36 /* bitrates */ +
656 - 3 /* DS params */ +
657 - 4 /* IBSS params */ +
658 + sizeof(struct ieee80211_hdr_3addr) +
659 + 12 /* struct ieee80211_mgmt.u.beacon */ +
660 + 2 + IEEE80211_MAX_SSID_LEN /* max SSID */ +
661 + 2 + 8 /* max Supported Rates */ +
662 + 3 /* max DS params */ +
663 + 4 /* IBSS params */ +
664 + 2 + (IEEE80211_MAX_SUPP_RATES - 8) +
665 + 2 + sizeof(struct ieee80211_ht_cap) +
666 + 2 + sizeof(struct ieee80211_ht_info) +
670 @@ -920,13 +1052,15 @@ int ieee80211_ibss_join(struct ieee80211
671 sdata->vif.bss_conf.beacon_int = params->beacon_interval;
673 sdata->u.ibss.channel = params->channel;
674 + sdata->u.ibss.channel_type = params->channel_type;
675 sdata->u.ibss.fixed_channel = params->channel_fixed;
677 /* fix ourselves to that channel now already */
678 if (params->channel_fixed) {
679 sdata->local->oper_channel = params->channel;
680 - WARN_ON(!ieee80211_set_channel_type(sdata->local, sdata,
681 - NL80211_CHAN_NO_HT));
682 + if(!ieee80211_set_channel_type(sdata->local, sdata,
683 + params->channel_type))
688 --- a/net/mac80211/rx.c
689 +++ b/net/mac80211/rx.c
690 @@ -2161,7 +2161,8 @@ ieee80211_rx_h_action(struct ieee80211_r
691 if (sdata->vif.type != NL80211_IFTYPE_STATION &&
692 sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
693 sdata->vif.type != NL80211_IFTYPE_AP &&
694 - sdata->vif.type != NL80211_IFTYPE_WDS)
695 + sdata->vif.type != NL80211_IFTYPE_WDS &&
696 + sdata->vif.type != NL80211_IFTYPE_ADHOC)
699 /* verify action_code is present */
700 @@ -2696,7 +2697,8 @@ static int prepare_for_handlers(struct i
702 rate_idx = status->rate_idx;
703 rx->sta = ieee80211_ibss_add_sta(sdata, bssid,
704 - hdr->addr2, BIT(rate_idx), GFP_ATOMIC);
705 + hdr->addr2, BIT(rate_idx), NULL,
709 case NL80211_IFTYPE_MESH_POINT:
710 --- a/net/mac80211/agg-rx.c
711 +++ b/net/mac80211/agg-rx.c
712 @@ -186,6 +186,8 @@ static void ieee80211_send_addba_resp(st
713 memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN);
714 else if (sdata->vif.type == NL80211_IFTYPE_WDS)
715 memcpy(mgmt->bssid, da, ETH_ALEN);
716 + else if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
717 + memcpy(mgmt->bssid, sdata->u.ibss.bssid, ETH_ALEN);
719 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
720 IEEE80211_STYPE_ACTION);