broadcom-wl: fix setup of virtual interfaces (patch by Nathan Hintz)
[openwrt.git] / 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:
This page took 0.081423 seconds and 5 git commands to generate.