Root/package/mac80211/patches/310-ibss_ht.patch

1--- a/include/net/cfg80211.h
2+++ b/include/net/cfg80211.h
3@@ -1038,6 +1038,7 @@ struct cfg80211_ibss_params {
4     u8 *ssid;
5     u8 *bssid;
6     struct ieee80211_channel *channel;
7+ enum nl80211_channel_type channel_type;
8     u8 *ie;
9     u8 ssid_len, ie_len;
10     u16 beacon_interval;
11@@ -2539,6 +2540,12 @@ struct cfg80211_bss *cfg80211_get_bss(st
12                       const u8 *bssid,
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,
17+ const u8 *bssid,
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/mac80211/ieee80211_i.h
25+++ b/net/mac80211/ieee80211_i.h
26@@ -439,6 +439,7 @@ struct ieee80211_if_ibss {
27     u8 ssid_len, ie_len;
28     u8 *ie;
29     struct ieee80211_channel *channel;
30+ enum nl80211_channel_type channel_type;
31 
32     unsigned long ibss_join_req;
33     /* probe response/beacon for IBSS */
34@@ -1121,6 +1122,7 @@ void ieee80211_ibss_notify_scan_complete
35 void ieee80211_ibss_setup_sdata(struct ieee80211_sub_if_data *sdata);
36 struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata,
37                     u8 *bssid, u8 *addr, u32 supp_rates,
38+ struct ieee80211_ht_cap *ht_cap,
39                     gfp_t gfp);
40 int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,
41             struct cfg80211_ibss_params *params);
42@@ -1373,6 +1375,12 @@ void ieee80211_recalc_smps(struct ieee80
43 size_t ieee80211_ie_split(const u8 *ies, size_t ielen,
44               const u8 *ids, int n_ids, size_t offset);
45 size_t ieee80211_ie_split_vendor(const u8 *ies, size_t ielen, size_t offset);
46+u8 *ieee80211_ie_build_ht_cap(u8 *pos, struct ieee80211_supported_band *sband,
47+ u16 cap);
48+u8 *ieee80211_ie_build_ht_info(u8 *pos,
49+ struct ieee80211_sta_ht_cap *ht_cap,
50+ struct ieee80211_channel *channel,
51+ enum nl80211_channel_type channel_type);
52 
53 /* internal work items */
54 void ieee80211_work_init(struct ieee80211_local *local);
55@@ -1401,6 +1409,8 @@ ieee80211_get_channel_mode(struct ieee80
56 bool ieee80211_set_channel_type(struct ieee80211_local *local,
57                 struct ieee80211_sub_if_data *sdata,
58                 enum nl80211_channel_type chantype);
59+enum nl80211_channel_type ieee80211_ht_info_to_channel_type(
60+ struct ieee80211_ht_info *ht_info);
61 
62 #ifdef CONFIG_MAC80211_NOINLINE
63 #define debug_noinline noinline
64--- a/net/mac80211/util.c
65+++ b/net/mac80211/util.c
66@@ -1007,23 +1007,8 @@ int ieee80211_build_preq_ies(struct ieee
67         offset = noffset;
68     }
69 
70- if (sband->ht_cap.ht_supported) {
71- u16 cap = sband->ht_cap.cap;
72- __le16 tmp;
73-
74- *pos++ = WLAN_EID_HT_CAPABILITY;
75- *pos++ = sizeof(struct ieee80211_ht_cap);
76- memset(pos, 0, sizeof(struct ieee80211_ht_cap));
77- tmp = cpu_to_le16(cap);
78- memcpy(pos, &tmp, sizeof(u16));
79- pos += sizeof(u16);
80- *pos++ = sband->ht_cap.ampdu_factor |
81- (sband->ht_cap.ampdu_density <<
82- IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT);
83- memcpy(pos, &sband->ht_cap.mcs, sizeof(sband->ht_cap.mcs));
84- pos += sizeof(sband->ht_cap.mcs);
85- pos += 2 + 4 + 1; /* ext info, BF cap, antsel */
86- }
87+ if (sband->ht_cap.ht_supported)
88+ pos = ieee80211_ie_build_ht_cap(pos, sband, sband->ht_cap.cap);
89 
90     /*
91      * If adding more here, adjust code in main.c
92@@ -1464,3 +1449,100 @@ size_t ieee80211_ie_split_vendor(const u
93 
94     return pos;
95 }
96+
97+u8 *ieee80211_ie_build_ht_cap(u8 *pos, struct ieee80211_supported_band *sband,
98+ u16 cap)
99+{
100+ __le16 tmp;
101+
102+ *pos++ = WLAN_EID_HT_CAPABILITY;
103+ *pos++ = sizeof(struct ieee80211_ht_cap);
104+ memset(pos, 0, sizeof(struct ieee80211_ht_cap));
105+
106+ /* capability flags */
107+ tmp = cpu_to_le16(cap);
108+ memcpy(pos, &tmp, sizeof(u16));
109+ pos += sizeof(u16);
110+
111+ /* AMPDU parameters */
112+ *pos++ = sband->ht_cap.ampdu_factor |
113+ (sband->ht_cap.ampdu_density <<
114+ IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT);
115+
116+ /* MCS set */
117+ memcpy(pos, &sband->ht_cap.mcs, sizeof(sband->ht_cap.mcs));
118+ pos += sizeof(sband->ht_cap.mcs);
119+
120+ /* extended capabilities */
121+ pos += sizeof(__le16);
122+
123+ /* BF capabilities */
124+ pos += sizeof(__le32);
125+
126+ /* antenna selection */
127+ pos += sizeof(u8);
128+
129+ return pos;
130+}
131+
132+u8 *ieee80211_ie_build_ht_info(u8 *pos,
133+ struct ieee80211_sta_ht_cap *ht_cap,
134+ struct ieee80211_channel *channel,
135+ enum nl80211_channel_type channel_type)
136+{
137+ struct ieee80211_ht_info *ht_info;
138+ /* Build HT Information */
139+ *pos++ = WLAN_EID_HT_INFORMATION;
140+ *pos++ = sizeof(struct ieee80211_ht_info);
141+ ht_info = (struct ieee80211_ht_info *)pos;
142+ ht_info->control_chan =
143+ ieee80211_frequency_to_channel(channel->center_freq);
144+ switch (channel_type) {
145+ case NL80211_CHAN_HT40MINUS:
146+ ht_info->ht_param = IEEE80211_HT_PARAM_CHA_SEC_BELOW;
147+ break;
148+ case NL80211_CHAN_HT40PLUS:
149+ ht_info->ht_param = IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
150+ break;
151+ case NL80211_CHAN_HT20:
152+ default:
153+ ht_info->ht_param = IEEE80211_HT_PARAM_CHA_SEC_NONE;
154+ break;
155+ }
156+ if (ht_cap->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40)
157+ ht_info->ht_param |= IEEE80211_HT_PARAM_CHAN_WIDTH_ANY;
158+ ht_info->operation_mode = 0x0000;
159+ ht_info->stbc_param = 0x0000;
160+
161+ /* It seems that Basic MCS set and Supported MCS set
162+ are identical for the first 10 bytes */
163+ memset(&ht_info->basic_set, 0, 16);
164+ memcpy(&ht_info->basic_set, &ht_cap->mcs, 10);
165+
166+ return pos + sizeof(struct ieee80211_ht_info);
167+}
168+
169+enum nl80211_channel_type ieee80211_ht_info_to_channel_type(
170+ struct ieee80211_ht_info *ht_info)
171+{
172+ enum nl80211_channel_type channel_type;
173+
174+ if (!ht_info)
175+ return NL80211_CHAN_NO_HT;
176+
177+ switch (ht_info->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) {
178+ case IEEE80211_HT_PARAM_CHA_SEC_NONE:
179+ channel_type = NL80211_CHAN_HT20;
180+ break;
181+ case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
182+ channel_type = NL80211_CHAN_HT40PLUS;
183+ break;
184+ case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
185+ channel_type = NL80211_CHAN_HT40MINUS;
186+ break;
187+ default:
188+ channel_type = NL80211_CHAN_NO_HT;
189+ }
190+
191+ return channel_type;
192+}
193--- a/net/mac80211/work.c
194+++ b/net/mac80211/work.c
195@@ -117,7 +117,6 @@ static void ieee80211_add_ht_ie(struct s
196     u8 *pos;
197     u32 flags = channel->flags;
198     u16 cap = sband->ht_cap.cap;
199- __le16 tmp;
200 
201     if (!sband->ht_cap.ht_supported)
202         return;
203@@ -168,34 +167,8 @@ static void ieee80211_add_ht_ie(struct s
204     }
205 
206     /* reserve and fill IE */
207-
208     pos = skb_put(skb, sizeof(struct ieee80211_ht_cap) + 2);
209- *pos++ = WLAN_EID_HT_CAPABILITY;
210- *pos++ = sizeof(struct ieee80211_ht_cap);
211- memset(pos, 0, sizeof(struct ieee80211_ht_cap));
212-
213- /* capability flags */
214- tmp = cpu_to_le16(cap);
215- memcpy(pos, &tmp, sizeof(u16));
216- pos += sizeof(u16);
217-
218- /* AMPDU parameters */
219- *pos++ = sband->ht_cap.ampdu_factor |
220- (sband->ht_cap.ampdu_density <<
221- IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT);
222-
223- /* MCS set */
224- memcpy(pos, &sband->ht_cap.mcs, sizeof(sband->ht_cap.mcs));
225- pos += sizeof(sband->ht_cap.mcs);
226-
227- /* extended capabilities */
228- pos += sizeof(__le16);
229-
230- /* BF capabilities */
231- pos += sizeof(__le32);
232-
233- /* antenna selection */
234- pos += sizeof(u8);
235+ ieee80211_ie_build_ht_cap(pos, sband, cap);
236 }
237 
238 static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata,
239--- a/net/wireless/scan.c
240+++ b/net/wireless/scan.c
241@@ -365,6 +365,18 @@ struct cfg80211_bss *cfg80211_get_bss(st
242                       const u8 *ssid, size_t ssid_len,
243                       u16 capa_mask, u16 capa_val)
244 {
245+ return cfg80211_get_bss_ht(wiphy, channel, bssid, ssid, ssid_len,
246+ capa_mask, capa_val, NL80211_CHAN_NO_HT);
247+}
248+EXPORT_SYMBOL(cfg80211_get_bss);
249+
250+struct cfg80211_bss *cfg80211_get_bss_ht(struct wiphy *wiphy,
251+ struct ieee80211_channel *channel,
252+ const u8 *bssid,
253+ const u8 *ssid, size_t ssid_len,
254+ u16 capa_mask, u16 capa_val,
255+ enum nl80211_channel_type channel_type)
256+{
257     struct cfg80211_registered_device *dev = wiphy_to_dev(wiphy);
258     struct cfg80211_internal_bss *bss, *res = NULL;
259     unsigned long now = jiffies;
260@@ -374,8 +386,27 @@ struct cfg80211_bss *cfg80211_get_bss(st
261     list_for_each_entry(bss, &dev->bss_list, list) {
262         if ((bss->pub.capability & capa_mask) != capa_val)
263             continue;
264- if (channel && bss->pub.channel != channel)
265- continue;
266+ if (channel) {
267+ if (bss->pub.channel != channel)
268+ continue;
269+ if (channel_type == NL80211_CHAN_HT40MINUS ||
270+ channel_type == NL80211_CHAN_HT40PLUS) {
271+ struct ieee80211_ht_info *ht_info;
272+ ht_info = (struct ieee80211_ht_info *)
273+ ieee80211_bss_get_ie(&bss->pub,
274+ WLAN_EID_HT_INFORMATION);
275+ if (!ht_info)
276+ continue;
277+ if (channel_type == NL80211_CHAN_HT40MINUS &&
278+ !(ht_info->ht_param &
279+ IEEE80211_HT_PARAM_CHA_SEC_BELOW))
280+ continue;
281+ if (channel_type == NL80211_CHAN_HT40PLUS &&
282+ !(ht_info->ht_param &
283+ IEEE80211_HT_PARAM_CHA_SEC_ABOVE))
284+ continue;
285+ }
286+ }
287         /* Don't get expired BSS structs */
288         if (time_after(now, bss->ts + IEEE80211_SCAN_RESULT_EXPIRE) &&
289             !atomic_read(&bss->hold))
290@@ -392,7 +423,7 @@ struct cfg80211_bss *cfg80211_get_bss(st
291         return NULL;
292     return &res->pub;
293 }
294-EXPORT_SYMBOL(cfg80211_get_bss);
295+EXPORT_SYMBOL(cfg80211_get_bss_ht);
296 
297 struct cfg80211_bss *cfg80211_get_mesh(struct wiphy *wiphy,
298                        struct ieee80211_channel *channel,
299--- a/net/wireless/nl80211.c
300+++ b/net/wireless/nl80211.c
301@@ -4282,13 +4282,42 @@ static int nl80211_join_ibss(struct sk_b
302         ibss.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
303     }
304 
305- ibss.channel = ieee80211_get_channel(wiphy,
306- nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]));
307+ if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) {
308+ enum nl80211_channel_type channel_type;
309+
310+ channel_type = nla_get_u32(
311+ info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]);
312+ if (channel_type != NL80211_CHAN_NO_HT &&
313+ channel_type != NL80211_CHAN_HT20 &&
314+ channel_type != NL80211_CHAN_HT40PLUS &&
315+ channel_type != NL80211_CHAN_HT40MINUS)
316+ return -EINVAL;
317+ ibss.channel_type = channel_type;
318+ } else {
319+ ibss.channel_type = NL80211_CHAN_NO_HT;
320+ }
321+
322+ ibss.channel = rdev_freq_to_chan(rdev,
323+ nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]),
324+ ibss.channel_type);
325+
326     if (!ibss.channel ||
327+ ibss.channel->flags & IEEE80211_CHAN_PASSIVE_SCAN ||
328         ibss.channel->flags & IEEE80211_CHAN_NO_IBSS ||
329         ibss.channel->flags & IEEE80211_CHAN_DISABLED)
330         return -EINVAL;
331 
332+#if 0
333+ if ((ibss.channel_type == NL80211_CHAN_HT40PLUS ||
334+ ibss.channel_type == NL80211_CHAN_HT40MINUS) &&
335+ !can_beacon_sec_chan(&rdev->wiphy, ibss.chan, ibss.channel_type)) {
336+ printk(KERN_DEBUG
337+ "cfg80211: Secondary channel not "
338+ "allowed to initiate communication\n");
339+ return -EINVAL;
340+ }
341+#endif
342+
343     ibss.channel_fixed = !!info->attrs[NL80211_ATTR_FREQ_FIXED];
344     ibss.privacy = !!info->attrs[NL80211_ATTR_PRIVACY];
345 
346--- a/net/mac80211/agg-rx.c
347+++ b/net/mac80211/agg-rx.c
348@@ -178,6 +178,8 @@ static void ieee80211_send_addba_resp(st
349         memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN);
350     else if (sdata->vif.type == NL80211_IFTYPE_WDS)
351         memcpy(mgmt->bssid, da, ETH_ALEN);
352+ else if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
353+ memcpy(mgmt->bssid, sdata->u.ibss.bssid, ETH_ALEN);
354 
355     mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
356                       IEEE80211_STYPE_ACTION);
357--- a/net/mac80211/agg-tx.c
358+++ b/net/mac80211/agg-tx.c
359@@ -84,6 +84,8 @@ static void ieee80211_send_addba_request
360         memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN);
361     else if (sdata->vif.type == NL80211_IFTYPE_STATION)
362         memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN);
363+ else if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
364+ memcpy(mgmt->bssid, sdata->u.ibss.bssid, ETH_ALEN);
365 
366     mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
367                       IEEE80211_STYPE_ACTION);
368@@ -400,7 +402,8 @@ int ieee80211_start_tx_ba_session(struct
369     if (sdata->vif.type != NL80211_IFTYPE_STATION &&
370         sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
371         sdata->vif.type != NL80211_IFTYPE_AP &&
372- sdata->vif.type != NL80211_IFTYPE_WDS)
373+ sdata->vif.type != NL80211_IFTYPE_WDS &&
374+ sdata->vif.type != NL80211_IFTYPE_ADHOC)
375         return -EINVAL;
376 
377     if (test_sta_flags(sta, WLAN_STA_BLOCK_BA)) {
378--- a/net/mac80211/ht.c
379+++ b/net/mac80211/ht.c
380@@ -203,6 +203,8 @@ void ieee80211_send_delba(struct ieee802
381         memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN);
382     else if (sdata->vif.type == NL80211_IFTYPE_STATION)
383         memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN);
384+ else if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
385+ memcpy(mgmt->bssid, sdata->u.ibss.bssid, ETH_ALEN);
386 
387     mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
388                       IEEE80211_STYPE_ACTION);
389--- a/net/mac80211/ibss.c
390+++ b/net/mac80211/ibss.c
391@@ -64,6 +64,7 @@ static void ieee80211_rx_mgmt_auth_ibss(
392 static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
393                       const u8 *bssid, const int beacon_int,
394                       struct ieee80211_channel *chan,
395+ enum nl80211_channel_type channel_type,
396                       const u32 basic_rates,
397                       const u16 capability, u64 tsf)
398 {
399@@ -104,8 +105,12 @@ static void __ieee80211_sta_join_ibss(st
400 
401     sdata->drop_unencrypted = capability & WLAN_CAPABILITY_PRIVACY ? 1 : 0;
402 
403+ /* entering a legacy IBSS. Use given HT configuration. */
404+ if (channel_type == NL80211_CHAN_NO_HT)
405+ channel_type = ifibss->channel_type;
406+
407     local->oper_channel = chan;
408- WARN_ON(!ieee80211_set_channel_type(local, sdata, NL80211_CHAN_NO_HT));
409+ WARN_ON(!ieee80211_set_channel_type(local, sdata, channel_type));
410     ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
411 
412     sband = local->hw.wiphy->bands[chan->band];
413@@ -171,6 +176,17 @@ static void __ieee80211_sta_join_ibss(st
414         memcpy(skb_put(skb, ifibss->ie_len),
415                ifibss->ie, ifibss->ie_len);
416 
417+ if (channel_type != NL80211_CHAN_NO_HT && sband->ht_cap.ht_supported) {
418+ pos = skb_put(skb, 4 +
419+ sizeof(struct ieee80211_ht_cap) +
420+ sizeof(struct ieee80211_ht_info));
421+ pos = ieee80211_ie_build_ht_cap(pos, sband, sband->ht_cap.cap);
422+ pos = ieee80211_ie_build_ht_info(pos,
423+ &sband->ht_cap,
424+ chan,
425+ channel_type);
426+ }
427+
428     if (local->hw.queues >= 4) {
429         pos = skb_put(skb, 9);
430         *pos++ = WLAN_EID_VENDOR_SPECIFIC;
431@@ -219,6 +235,8 @@ static void ieee80211_sta_join_ibss(stru
432     u32 basic_rates;
433     int i, j;
434     u16 beacon_int = cbss->beacon_interval;
435+ const u8 *ht_info_ie;
436+ enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT;
437 
438     lockdep_assert_held(&sdata->u.ibss.mtx);
439 
440@@ -242,9 +260,15 @@ static void ieee80211_sta_join_ibss(stru
441         }
442     }
443 
444+ ht_info_ie = ieee80211_bss_get_ie(cbss, WLAN_EID_HT_INFORMATION);
445+ if (ht_info_ie)
446+ channel_type = ieee80211_ht_info_to_channel_type(
447+ (struct ieee80211_ht_info *) (ht_info_ie + 2));
448+
449     __ieee80211_sta_join_ibss(sdata, cbss->bssid,
450                   beacon_int,
451                   cbss->channel,
452+ channel_type,
453                   basic_rates,
454                   cbss->capability,
455                   cbss->tsf);
456@@ -310,11 +334,65 @@ static void ieee80211_rx_bss_info(struct
457             } else
458                 sta = ieee80211_ibss_add_sta(sdata, mgmt->bssid,
459                         mgmt->sa, supp_rates,
460- GFP_ATOMIC);
461+ elems->ht_cap_elem, GFP_ATOMIC);
462         }
463 
464- if (sta && elems->wmm_info)
465- set_sta_flags(sta, WLAN_STA_WME);
466+ if (sta) {
467+ if (elems->wmm_info)
468+ set_sta_flags(sta, WLAN_STA_WME);
469+
470+ if (elems->ht_info_elem) {
471+ struct ieee80211_supported_band *sband =
472+ local->hw.wiphy->bands[channel->band];
473+ enum nl80211_channel_type channel_type;
474+
475+ channel_type =
476+ ieee80211_ht_info_to_channel_type(
477+ elems->ht_info_elem);
478+ if (channel_type != local->_oper_channel_type) {
479+ struct sk_buff *skb =
480+ sdata->u.ibss.presp;
481+ struct sk_buff *nskb;
482+ u8 *ht_ie;
483+
484+ nskb = skb_copy(skb, GFP_ATOMIC);
485+ ht_ie = (u8 *) cfg80211_find_ie(
486+ WLAN_EID_HT_CAPABILITY,
487+ nskb->data + 24 +
488+ sizeof(mgmt->u.beacon),
489+ nskb->len - 24 -
490+ sizeof(mgmt->u.beacon));
491+
492+ if (!ht_ie)
493+ ht_ie = skb_put(nskb, 4 +
494+ sizeof(struct ieee80211_ht_cap) +
495+ sizeof(struct ieee80211_ht_info));
496+ ht_ie = ieee80211_ie_build_ht_cap(ht_ie,
497+ sband,
498+ sband->ht_cap.cap);
499+ ht_ie = ieee80211_ie_build_ht_info(
500+ ht_ie,
501+ &sband->ht_cap,
502+ channel,
503+ channel_type);
504+ sdata->u.ibss.presp = nskb;
505+ kfree_skb(skb);
506+
507+ local->_oper_channel_type =
508+ channel_type;
509+ WARN_ON(!ieee80211_set_channel_type(
510+ local,
511+ sdata,
512+ channel_type));
513+ ieee80211_hw_config(local,
514+ IEEE80211_CONF_CHANGE_CHANNEL);
515+ }
516+ ieee80211_ht_cap_ie_to_sta_ht_cap(sband,
517+ elems->ht_cap_elem,
518+ &sta->sta.ht_cap);
519+
520+ }
521+ }
522 
523         rcu_read_unlock();
524     }
525@@ -404,7 +482,7 @@ static void ieee80211_rx_bss_info(struct
526         ieee80211_sta_join_ibss(sdata, bss);
527         supp_rates = ieee80211_sta_get_rates(local, elems, band);
528         ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa,
529- supp_rates, GFP_KERNEL);
530+ supp_rates, elems->ht_cap_elem, GFP_KERNEL);
531     }
532 
533  put_bss:
534@@ -417,7 +495,8 @@ static void ieee80211_rx_bss_info(struct
535  * must be callable in atomic context.
536  */
537 struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata,
538- u8 *bssid,u8 *addr, u32 supp_rates,
539+ u8 *bssid, u8 *addr, u32 supp_rates,
540+ struct ieee80211_ht_cap *ht_cap,
541                     gfp_t gfp)
542 {
543     struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
544@@ -458,6 +537,11 @@ struct sta_info *ieee80211_ibss_add_sta(
545     sta->sta.supp_rates[band] = supp_rates |
546             ieee80211_mandatory_rates(local, band);
547 
548+ /* fill in ht rates */
549+ if (ht_cap)
550+ ieee80211_ht_cap_ie_to_sta_ht_cap(local->hw.wiphy->bands[band],
551+ ht_cap, &sta->sta.ht_cap);
552+
553     rate_control_rate_init(sta);
554 
555     /* If it fails, maybe we raced another insertion? */
556@@ -556,8 +640,8 @@ static void ieee80211_sta_create_ibss(st
557         sdata->drop_unencrypted = 0;
558 
559     __ieee80211_sta_join_ibss(sdata, bssid, sdata->vif.bss_conf.beacon_int,
560- ifibss->channel, ifibss->basic_rates,
561- capability, 0);
562+ ifibss->channel, ifibss->channel_type,
563+ ifibss->basic_rates, capability, 0);
564 }
565 
566 /*
567@@ -594,10 +678,10 @@ static void ieee80211_sta_find_ibss(stru
568         chan = ifibss->channel;
569     if (!is_zero_ether_addr(ifibss->bssid))
570         bssid = ifibss->bssid;
571- cbss = cfg80211_get_bss(local->hw.wiphy, chan, bssid,
572+ cbss = cfg80211_get_bss_ht(local->hw.wiphy, chan, bssid,
573                 ifibss->ssid, ifibss->ssid_len,
574                 WLAN_CAPABILITY_IBSS | WLAN_CAPABILITY_PRIVACY,
575- capability);
576+ capability, ifibss->channel_type);
577 
578     if (cbss) {
579         struct ieee80211_bss *bss;
580@@ -896,10 +980,15 @@ int ieee80211_ibss_join(struct ieee80211
581     struct sk_buff *skb;
582 
583     skb = dev_alloc_skb(sdata->local->hw.extra_tx_headroom +
584- 36 /* bitrates */ +
585- 34 /* SSID */ +
586- 3 /* DS params */ +
587- 4 /* IBSS params */ +
588+ sizeof(struct ieee80211_hdr_3addr) +
589+ 12 /* struct ieee80211_mgmt.u.beacon */ +
590+ 2 + IEEE80211_MAX_SSID_LEN /* max SSID */ +
591+ 2 + 8 /* max Supported Rates */ +
592+ 3 /* max DS params */ +
593+ 4 /* IBSS params */ +
594+ 2 + (IEEE80211_MAX_SUPP_RATES - 8) +
595+ 2 + sizeof(struct ieee80211_ht_cap) +
596+ 2 + sizeof(struct ieee80211_ht_info) +
597                 params->ie_len);
598     if (!skb)
599         return -ENOMEM;
600@@ -920,13 +1009,14 @@ int ieee80211_ibss_join(struct ieee80211
601     sdata->vif.bss_conf.beacon_int = params->beacon_interval;
602 
603     sdata->u.ibss.channel = params->channel;
604+ sdata->u.ibss.channel_type = params->channel_type;
605     sdata->u.ibss.fixed_channel = params->channel_fixed;
606 
607     /* fix ourselves to that channel now already */
608     if (params->channel_fixed) {
609         sdata->local->oper_channel = params->channel;
610         WARN_ON(!ieee80211_set_channel_type(sdata->local, sdata,
611- NL80211_CHAN_NO_HT));
612+ params->channel_type));
613     }
614 
615     if (params->ie) {
616--- a/net/mac80211/rx.c
617+++ b/net/mac80211/rx.c
618@@ -2138,7 +2138,8 @@ ieee80211_rx_h_action(struct ieee80211_r
619         if (sdata->vif.type != NL80211_IFTYPE_STATION &&
620             sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
621             sdata->vif.type != NL80211_IFTYPE_AP &&
622- sdata->vif.type != NL80211_IFTYPE_WDS)
623+ sdata->vif.type != NL80211_IFTYPE_WDS &&
624+ sdata->vif.type != NL80211_IFTYPE_ADHOC)
625             break;
626 
627         /* verify action_code is present */
628@@ -2654,7 +2655,8 @@ static int prepare_for_handlers(struct i
629             else
630                 rate_idx = status->rate_idx;
631             rx->sta = ieee80211_ibss_add_sta(sdata, bssid,
632- hdr->addr2, BIT(rate_idx), GFP_ATOMIC);
633+ hdr->addr2, BIT(rate_idx), NULL,
634+ GFP_ATOMIC);
635         }
636         break;
637     case NL80211_IFTYPE_MESH_POINT:
638

Archive Download this file



interactive