aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/mac80211/agg-rx.c2
-rw-r--r--net/mac80211/agg-tx.c5
-rw-r--r--net/mac80211/ht.c2
-rw-r--r--net/mac80211/ibss.c83
-rw-r--r--net/mac80211/ieee80211_i.h1
-rw-r--r--net/mac80211/main.c3
-rw-r--r--net/mac80211/rx.c3
7 files changed, 87 insertions, 12 deletions
diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c
index e844e5a38408..96debba2c407 100644
--- a/net/mac80211/agg-rx.c
+++ b/net/mac80211/agg-rx.c
@@ -185,6 +185,8 @@ static void ieee80211_send_addba_resp(struct ieee80211_sub_if_data *sdata, u8 *d
185 memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN); 185 memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN);
186 else if (sdata->vif.type == NL80211_IFTYPE_STATION) 186 else if (sdata->vif.type == NL80211_IFTYPE_STATION)
187 memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN); 187 memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN);
188 else if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
189 memcpy(mgmt->bssid, sdata->u.ibss.bssid, ETH_ALEN);
188 190
189 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | 191 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
190 IEEE80211_STYPE_ACTION); 192 IEEE80211_STYPE_ACTION);
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c
index 9bfe28c9ab59..c45fa5df0d41 100644
--- a/net/mac80211/agg-tx.c
+++ b/net/mac80211/agg-tx.c
@@ -83,6 +83,8 @@ static void ieee80211_send_addba_request(struct ieee80211_sub_if_data *sdata,
83 memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN); 83 memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN);
84 else if (sdata->vif.type == NL80211_IFTYPE_STATION) 84 else if (sdata->vif.type == NL80211_IFTYPE_STATION)
85 memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN); 85 memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN);
86 else if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
87 memcpy(mgmt->bssid, sdata->u.ibss.bssid, ETH_ALEN);
86 88
87 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | 89 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
88 IEEE80211_STYPE_ACTION); 90 IEEE80211_STYPE_ACTION);
@@ -419,7 +421,8 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid,
419 if (sdata->vif.type != NL80211_IFTYPE_STATION && 421 if (sdata->vif.type != NL80211_IFTYPE_STATION &&
420 sdata->vif.type != NL80211_IFTYPE_MESH_POINT && 422 sdata->vif.type != NL80211_IFTYPE_MESH_POINT &&
421 sdata->vif.type != NL80211_IFTYPE_AP_VLAN && 423 sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
422 sdata->vif.type != NL80211_IFTYPE_AP) 424 sdata->vif.type != NL80211_IFTYPE_AP &&
425 sdata->vif.type != NL80211_IFTYPE_ADHOC)
423 return -EINVAL; 426 return -EINVAL;
424 427
425 if (test_sta_flag(sta, WLAN_STA_BLOCK_BA)) { 428 if (test_sta_flag(sta, WLAN_STA_BLOCK_BA)) {
diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c
index d3eafaefb16b..e0a396bdf883 100644
--- a/net/mac80211/ht.c
+++ b/net/mac80211/ht.c
@@ -282,6 +282,8 @@ void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata,
282 memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN); 282 memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN);
283 else if (sdata->vif.type == NL80211_IFTYPE_STATION) 283 else if (sdata->vif.type == NL80211_IFTYPE_STATION)
284 memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN); 284 memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN);
285 else if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
286 memcpy(mgmt->bssid, sdata->u.ibss.bssid, ETH_ALEN);
285 287
286 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | 288 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
287 IEEE80211_STYPE_ACTION); 289 IEEE80211_STYPE_ACTION);
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index a82f6b4adb58..3f830ac159e5 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -77,6 +77,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
77 struct cfg80211_bss *bss; 77 struct cfg80211_bss *bss;
78 u32 bss_change; 78 u32 bss_change;
79 u8 supp_rates[IEEE80211_MAX_SUPP_RATES]; 79 u8 supp_rates[IEEE80211_MAX_SUPP_RATES];
80 enum nl80211_channel_type channel_type;
80 81
81 lockdep_assert_held(&ifibss->mtx); 82 lockdep_assert_held(&ifibss->mtx);
82 83
@@ -105,8 +106,16 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
105 106
106 sdata->drop_unencrypted = capability & WLAN_CAPABILITY_PRIVACY ? 1 : 0; 107 sdata->drop_unencrypted = capability & WLAN_CAPABILITY_PRIVACY ? 1 : 0;
107 108
108 local->oper_channel = chan; 109 channel_type = ifibss->channel_type;
109 WARN_ON(!ieee80211_set_channel_type(local, sdata, NL80211_CHAN_NO_HT)); 110 if (channel_type > NL80211_CHAN_HT20 &&
111 !cfg80211_can_beacon_sec_chan(local->hw.wiphy, chan, channel_type))
112 channel_type = NL80211_CHAN_HT20;
113 if (!ieee80211_set_channel_type(local, sdata, channel_type)) {
114 /* can only fail due to HT40+/- mismatch */
115 channel_type = NL80211_CHAN_HT20;
116 WARN_ON(!ieee80211_set_channel_type(local, sdata,
117 NL80211_CHAN_HT20));
118 }
110 ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); 119 ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
111 120
112 sband = local->hw.wiphy->bands[chan->band]; 121 sband = local->hw.wiphy->bands[chan->band];
@@ -172,6 +181,19 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
172 memcpy(skb_put(skb, ifibss->ie_len), 181 memcpy(skb_put(skb, ifibss->ie_len),
173 ifibss->ie, ifibss->ie_len); 182 ifibss->ie, ifibss->ie_len);
174 183
184 /* add HT capability and information IEs */
185 if (channel_type && sband->ht_cap.ht_supported) {
186 pos = skb_put(skb, 4 +
187 sizeof(struct ieee80211_ht_cap) +
188 sizeof(struct ieee80211_ht_info));
189 pos = ieee80211_ie_build_ht_cap(pos, &sband->ht_cap,
190 sband->ht_cap.cap);
191 pos = ieee80211_ie_build_ht_info(pos,
192 &sband->ht_cap,
193 chan,
194 channel_type);
195 }
196
175 if (local->hw.queues >= 4) { 197 if (local->hw.queues >= 4) {
176 pos = skb_put(skb, 9); 198 pos = skb_put(skb, 9);
177 *pos++ = WLAN_EID_VENDOR_SPECIFIC; 199 *pos++ = WLAN_EID_VENDOR_SPECIFIC;
@@ -195,6 +217,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
195 bss_change |= BSS_CHANGED_BEACON; 217 bss_change |= BSS_CHANGED_BEACON;
196 bss_change |= BSS_CHANGED_BEACON_ENABLED; 218 bss_change |= BSS_CHANGED_BEACON_ENABLED;
197 bss_change |= BSS_CHANGED_BASIC_RATES; 219 bss_change |= BSS_CHANGED_BASIC_RATES;
220 bss_change |= BSS_CHANGED_HT;
198 bss_change |= BSS_CHANGED_IBSS; 221 bss_change |= BSS_CHANGED_IBSS;
199 sdata->vif.bss_conf.ibss_joined = true; 222 sdata->vif.bss_conf.ibss_joined = true;
200 ieee80211_bss_info_change_notify(sdata, bss_change); 223 ieee80211_bss_info_change_notify(sdata, bss_change);
@@ -268,6 +291,8 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
268 u64 beacon_timestamp, rx_timestamp; 291 u64 beacon_timestamp, rx_timestamp;
269 u32 supp_rates = 0; 292 u32 supp_rates = 0;
270 enum ieee80211_band band = rx_status->band; 293 enum ieee80211_band band = rx_status->band;
294 struct ieee80211_supported_band *sband = local->hw.wiphy->bands[band];
295 bool rates_updated = false;
271 296
272 if (elems->ds_params && elems->ds_params_len == 1) 297 if (elems->ds_params && elems->ds_params_len == 1)
273 freq = ieee80211_channel_to_frequency(elems->ds_params[0], 298 freq = ieee80211_channel_to_frequency(elems->ds_params[0],
@@ -307,7 +332,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
307 prev_rates, 332 prev_rates,
308 sta->sta.supp_rates[band]); 333 sta->sta.supp_rates[band]);
309#endif 334#endif
310 rate_control_rate_init(sta); 335 rates_updated = true;
311 } 336 }
312 } else 337 } else
313 sta = ieee80211_ibss_add_sta(sdata, mgmt->bssid, 338 sta = ieee80211_ibss_add_sta(sdata, mgmt->bssid,
@@ -318,6 +343,39 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
318 if (sta && elems->wmm_info) 343 if (sta && elems->wmm_info)
319 set_sta_flag(sta, WLAN_STA_WME); 344 set_sta_flag(sta, WLAN_STA_WME);
320 345
346 if (sta && elems->ht_info_elem && elems->ht_cap_elem &&
347 sdata->u.ibss.channel_type != NL80211_CHAN_NO_HT) {
348 /* we both use HT */
349 struct ieee80211_sta_ht_cap sta_ht_cap_new;
350 enum nl80211_channel_type channel_type =
351 ieee80211_ht_info_to_channel_type(
352 elems->ht_info_elem);
353
354 ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband,
355 elems->ht_cap_elem,
356 &sta_ht_cap_new);
357
358 /*
359 * fall back to HT20 if we don't use or use
360 * the other extension channel
361 */
362 if ((channel_type == NL80211_CHAN_HT40MINUS ||
363 channel_type == NL80211_CHAN_HT40PLUS) &&
364 channel_type != sdata->u.ibss.channel_type)
365 sta_ht_cap_new.cap &=
366 ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
367
368 if (memcmp(&sta->sta.ht_cap, &sta_ht_cap_new,
369 sizeof(sta_ht_cap_new))) {
370 memcpy(&sta->sta.ht_cap, &sta_ht_cap_new,
371 sizeof(sta_ht_cap_new));
372 rates_updated = true;
373 }
374 }
375
376 if (sta && rates_updated)
377 rate_control_rate_init(sta);
378
321 rcu_read_unlock(); 379 rcu_read_unlock();
322 } 380 }
323 381
@@ -899,10 +957,15 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,
899 u32 changed = 0; 957 u32 changed = 0;
900 958
901 skb = dev_alloc_skb(sdata->local->hw.extra_tx_headroom + 959 skb = dev_alloc_skb(sdata->local->hw.extra_tx_headroom +
902 36 /* bitrates */ + 960 sizeof(struct ieee80211_hdr_3addr) +
903 34 /* SSID */ + 961 12 /* struct ieee80211_mgmt.u.beacon */ +
904 3 /* DS params */ + 962 2 + IEEE80211_MAX_SSID_LEN /* max SSID */ +
905 4 /* IBSS params */ + 963 2 + 8 /* max Supported Rates */ +
964 3 /* max DS params */ +
965 4 /* IBSS params */ +
966 2 + (IEEE80211_MAX_SUPP_RATES - 8) +
967 2 + sizeof(struct ieee80211_ht_cap) +
968 2 + sizeof(struct ieee80211_ht_info) +
906 params->ie_len); 969 params->ie_len);
907 if (!skb) 970 if (!skb)
908 return -ENOMEM; 971 return -ENOMEM;
@@ -923,13 +986,15 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,
923 sdata->vif.bss_conf.beacon_int = params->beacon_interval; 986 sdata->vif.bss_conf.beacon_int = params->beacon_interval;
924 987
925 sdata->u.ibss.channel = params->channel; 988 sdata->u.ibss.channel = params->channel;
989 sdata->u.ibss.channel_type = params->channel_type;
926 sdata->u.ibss.fixed_channel = params->channel_fixed; 990 sdata->u.ibss.fixed_channel = params->channel_fixed;
927 991
928 /* fix ourselves to that channel now already */ 992 /* fix ourselves to that channel now already */
929 if (params->channel_fixed) { 993 if (params->channel_fixed) {
930 sdata->local->oper_channel = params->channel; 994 sdata->local->oper_channel = params->channel;
931 WARN_ON(!ieee80211_set_channel_type(sdata->local, sdata, 995 if (!ieee80211_set_channel_type(sdata->local, sdata,
932 NL80211_CHAN_NO_HT)); 996 params->channel_type))
997 return -EINVAL;
933 } 998 }
934 999
935 if (params->ie) { 1000 if (params->ie) {
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index bdefa6ba3f4c..96fe75410bbe 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -474,6 +474,7 @@ struct ieee80211_if_ibss {
474 u8 ssid_len, ie_len; 474 u8 ssid_len, ie_len;
475 u8 *ie; 475 u8 *ie;
476 struct ieee80211_channel *channel; 476 struct ieee80211_channel *channel;
477 enum nl80211_channel_type channel_type;
477 478
478 unsigned long ibss_join_req; 479 unsigned long ibss_join_req;
479 /* probe response/beacon for IBSS */ 480 /* probe response/beacon for IBSS */
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 24cc50b963a9..60198ac664a0 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -570,7 +570,8 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
570 WIPHY_FLAG_OFFCHAN_TX | 570 WIPHY_FLAG_OFFCHAN_TX |
571 WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; 571 WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
572 572
573 wiphy->features = NL80211_FEATURE_SK_TX_STATUS; 573 wiphy->features = NL80211_FEATURE_SK_TX_STATUS |
574 NL80211_FEATURE_HT_IBSS;
574 575
575 if (!ops->set_key) 576 if (!ops->set_key)
576 wiphy->flags |= WIPHY_FLAG_IBSS_RSN; 577 wiphy->flags |= WIPHY_FLAG_IBSS_RSN;
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index daf5cde65b30..2a85fdfebde2 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -2237,7 +2237,8 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
2237 if (sdata->vif.type != NL80211_IFTYPE_STATION && 2237 if (sdata->vif.type != NL80211_IFTYPE_STATION &&
2238 sdata->vif.type != NL80211_IFTYPE_MESH_POINT && 2238 sdata->vif.type != NL80211_IFTYPE_MESH_POINT &&
2239 sdata->vif.type != NL80211_IFTYPE_AP_VLAN && 2239 sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
2240 sdata->vif.type != NL80211_IFTYPE_AP) 2240 sdata->vif.type != NL80211_IFTYPE_AP &&
2241 sdata->vif.type != NL80211_IFTYPE_ADHOC)
2241 break; 2242 break;
2242 2243
2243 /* verify action_code is present */ 2244 /* verify action_code is present */