diff options
-rw-r--r-- | net/mac80211/agg-rx.c | 2 | ||||
-rw-r--r-- | net/mac80211/agg-tx.c | 5 | ||||
-rw-r--r-- | net/mac80211/ht.c | 2 | ||||
-rw-r--r-- | net/mac80211/ibss.c | 83 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 1 | ||||
-rw-r--r-- | net/mac80211/main.c | 3 | ||||
-rw-r--r-- | net/mac80211/rx.c | 3 |
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 */ |