diff options
author | John W. Linville <linville@tuxdriver.com> | 2012-11-26 14:46:41 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2012-11-26 14:46:41 -0500 |
commit | 62c8003ecb973986958e9dade4a7e598349caf48 (patch) | |
tree | 0e831639cd6449c2955234cfc37ef46481c788d1 /net/mac80211 | |
parent | e4cb3ff9311e0817e65cda7bc53898348aab7527 (diff) | |
parent | ec816087e8978b74c1bd5fae0e335dd97d964e9f (diff) |
Merge branch 'for-john' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next
Diffstat (limited to 'net/mac80211')
-rw-r--r-- | net/mac80211/cfg.c | 137 | ||||
-rw-r--r-- | net/mac80211/chan.c | 128 | ||||
-rw-r--r-- | net/mac80211/debugfs_netdev.c | 2 | ||||
-rw-r--r-- | net/mac80211/driver-ops.h | 5 | ||||
-rw-r--r-- | net/mac80211/ibss.c | 46 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 22 | ||||
-rw-r--r-- | net/mac80211/iface.c | 5 | ||||
-rw-r--r-- | net/mac80211/main.c | 23 | ||||
-rw-r--r-- | net/mac80211/mesh.c | 36 | ||||
-rw-r--r-- | net/mac80211/mesh.h | 14 | ||||
-rw-r--r-- | net/mac80211/mesh_plink.c | 47 | ||||
-rw-r--r-- | net/mac80211/mesh_sync.c | 2 | ||||
-rw-r--r-- | net/mac80211/mlme.c | 94 | ||||
-rw-r--r-- | net/mac80211/offchannel.c | 8 | ||||
-rw-r--r-- | net/mac80211/rate.c | 5 | ||||
-rw-r--r-- | net/mac80211/rate.h | 2 | ||||
-rw-r--r-- | net/mac80211/rx.c | 41 | ||||
-rw-r--r-- | net/mac80211/scan.c | 9 | ||||
-rw-r--r-- | net/mac80211/sta_info.c | 2 | ||||
-rw-r--r-- | net/mac80211/sta_info.h | 8 | ||||
-rw-r--r-- | net/mac80211/trace.h | 29 | ||||
-rw-r--r-- | net/mac80211/tx.c | 20 | ||||
-rw-r--r-- | net/mac80211/util.c | 59 | ||||
-rw-r--r-- | net/mac80211/wme.c | 40 |
24 files changed, 389 insertions, 395 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 6733b374c821..4965aa6424ec 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -370,30 +370,32 @@ static int ieee80211_config_default_mgmt_key(struct wiphy *wiphy, | |||
370 | return 0; | 370 | return 0; |
371 | } | 371 | } |
372 | 372 | ||
373 | static void rate_idx_to_bitrate(struct rate_info *rate, struct sta_info *sta, int idx) | ||
374 | { | ||
375 | enum ieee80211_band band = ieee80211_get_sdata_band(sta->sdata); | ||
376 | |||
377 | if (!(rate->flags & RATE_INFO_FLAGS_MCS)) { | ||
378 | struct ieee80211_supported_band *sband; | ||
379 | sband = sta->local->hw.wiphy->bands[band]; | ||
380 | rate->legacy = sband->bitrates[idx].bitrate; | ||
381 | } else | ||
382 | rate->mcs = idx; | ||
383 | } | ||
384 | |||
385 | void sta_set_rate_info_tx(struct sta_info *sta, | 373 | void sta_set_rate_info_tx(struct sta_info *sta, |
386 | const struct ieee80211_tx_rate *rate, | 374 | const struct ieee80211_tx_rate *rate, |
387 | struct rate_info *rinfo) | 375 | struct rate_info *rinfo) |
388 | { | 376 | { |
389 | rinfo->flags = 0; | 377 | rinfo->flags = 0; |
390 | if (rate->flags & IEEE80211_TX_RC_MCS) | 378 | if (rate->flags & IEEE80211_TX_RC_MCS) { |
391 | rinfo->flags |= RATE_INFO_FLAGS_MCS; | 379 | rinfo->flags |= RATE_INFO_FLAGS_MCS; |
380 | rinfo->mcs = rate->idx; | ||
381 | } else if (rate->flags & IEEE80211_TX_RC_VHT_MCS) { | ||
382 | rinfo->flags |= RATE_INFO_FLAGS_VHT_MCS; | ||
383 | rinfo->mcs = ieee80211_rate_get_vht_mcs(rate); | ||
384 | rinfo->nss = ieee80211_rate_get_vht_nss(rate); | ||
385 | } else { | ||
386 | struct ieee80211_supported_band *sband; | ||
387 | sband = sta->local->hw.wiphy->bands[ | ||
388 | ieee80211_get_sdata_band(sta->sdata)]; | ||
389 | rinfo->legacy = sband->bitrates[rate->idx].bitrate; | ||
390 | } | ||
392 | if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) | 391 | if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) |
393 | rinfo->flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; | 392 | rinfo->flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; |
393 | if (rate->flags & IEEE80211_TX_RC_80_MHZ_WIDTH) | ||
394 | rinfo->flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH; | ||
395 | if (rate->flags & IEEE80211_TX_RC_160_MHZ_WIDTH) | ||
396 | rinfo->flags |= RATE_INFO_FLAGS_160_MHZ_WIDTH; | ||
394 | if (rate->flags & IEEE80211_TX_RC_SHORT_GI) | 397 | if (rate->flags & IEEE80211_TX_RC_SHORT_GI) |
395 | rinfo->flags |= RATE_INFO_FLAGS_SHORT_GI; | 398 | rinfo->flags |= RATE_INFO_FLAGS_SHORT_GI; |
396 | rate_idx_to_bitrate(rinfo, sta, rate->idx); | ||
397 | } | 399 | } |
398 | 400 | ||
399 | static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) | 401 | static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) |
@@ -444,13 +446,32 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) | |||
444 | sta_set_rate_info_tx(sta, &sta->last_tx_rate, &sinfo->txrate); | 446 | sta_set_rate_info_tx(sta, &sta->last_tx_rate, &sinfo->txrate); |
445 | 447 | ||
446 | sinfo->rxrate.flags = 0; | 448 | sinfo->rxrate.flags = 0; |
447 | if (sta->last_rx_rate_flag & RX_FLAG_HT) | 449 | if (sta->last_rx_rate_flag & RX_FLAG_HT) { |
448 | sinfo->rxrate.flags |= RATE_INFO_FLAGS_MCS; | 450 | sinfo->rxrate.flags |= RATE_INFO_FLAGS_MCS; |
451 | sinfo->rxrate.mcs = sta->last_rx_rate_idx; | ||
452 | } else if (sta->last_rx_rate_flag & RX_FLAG_VHT) { | ||
453 | sinfo->rxrate.flags |= RATE_INFO_FLAGS_VHT_MCS; | ||
454 | sinfo->rxrate.nss = sta->last_rx_rate_vht_nss; | ||
455 | sinfo->rxrate.mcs = sta->last_rx_rate_idx; | ||
456 | } else { | ||
457 | struct ieee80211_supported_band *sband; | ||
458 | |||
459 | sband = sta->local->hw.wiphy->bands[ | ||
460 | ieee80211_get_sdata_band(sta->sdata)]; | ||
461 | sinfo->rxrate.legacy = | ||
462 | sband->bitrates[sta->last_rx_rate_idx].bitrate; | ||
463 | } | ||
464 | |||
449 | if (sta->last_rx_rate_flag & RX_FLAG_40MHZ) | 465 | if (sta->last_rx_rate_flag & RX_FLAG_40MHZ) |
450 | sinfo->rxrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; | 466 | sinfo->rxrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; |
451 | if (sta->last_rx_rate_flag & RX_FLAG_SHORT_GI) | 467 | if (sta->last_rx_rate_flag & RX_FLAG_SHORT_GI) |
452 | sinfo->rxrate.flags |= RATE_INFO_FLAGS_SHORT_GI; | 468 | sinfo->rxrate.flags |= RATE_INFO_FLAGS_SHORT_GI; |
453 | rate_idx_to_bitrate(&sinfo->rxrate, sta, sta->last_rx_rate_idx); | 469 | if (sta->last_rx_rate_flag & RX_FLAG_80MHZ) |
470 | sinfo->rxrate.flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH; | ||
471 | if (sta->last_rx_rate_flag & RX_FLAG_80P80MHZ) | ||
472 | sinfo->rxrate.flags |= RATE_INFO_FLAGS_80P80_MHZ_WIDTH; | ||
473 | if (sta->last_rx_rate_flag & RX_FLAG_160MHZ) | ||
474 | sinfo->rxrate.flags |= RATE_INFO_FLAGS_160_MHZ_WIDTH; | ||
454 | 475 | ||
455 | if (ieee80211_vif_is_mesh(&sdata->vif)) { | 476 | if (ieee80211_vif_is_mesh(&sdata->vif)) { |
456 | #ifdef CONFIG_MAC80211_MESH | 477 | #ifdef CONFIG_MAC80211_MESH |
@@ -615,7 +636,7 @@ do_survey: | |||
615 | rcu_read_lock(); | 636 | rcu_read_lock(); |
616 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); | 637 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); |
617 | if (chanctx_conf) | 638 | if (chanctx_conf) |
618 | channel = chanctx_conf->channel; | 639 | channel = chanctx_conf->def.chan; |
619 | else | 640 | else |
620 | channel = NULL; | 641 | channel = NULL; |
621 | rcu_read_unlock(); | 642 | rcu_read_unlock(); |
@@ -735,15 +756,13 @@ static int ieee80211_get_station(struct wiphy *wiphy, struct net_device *dev, | |||
735 | } | 756 | } |
736 | 757 | ||
737 | static int ieee80211_set_monitor_channel(struct wiphy *wiphy, | 758 | static int ieee80211_set_monitor_channel(struct wiphy *wiphy, |
738 | struct ieee80211_channel *chan, | 759 | struct cfg80211_chan_def *chandef) |
739 | enum nl80211_channel_type channel_type) | ||
740 | { | 760 | { |
741 | struct ieee80211_local *local = wiphy_priv(wiphy); | 761 | struct ieee80211_local *local = wiphy_priv(wiphy); |
742 | struct ieee80211_sub_if_data *sdata; | 762 | struct ieee80211_sub_if_data *sdata; |
743 | int ret = 0; | 763 | int ret = 0; |
744 | 764 | ||
745 | if (local->monitor_channel == chan && | 765 | if (cfg80211_chandef_identical(&local->monitor_chandef, chandef)) |
746 | local->monitor_channel_type == channel_type) | ||
747 | return 0; | 766 | return 0; |
748 | 767 | ||
749 | mutex_lock(&local->iflist_mtx); | 768 | mutex_lock(&local->iflist_mtx); |
@@ -753,20 +772,17 @@ static int ieee80211_set_monitor_channel(struct wiphy *wiphy, | |||
753 | lockdep_is_held(&local->iflist_mtx)); | 772 | lockdep_is_held(&local->iflist_mtx)); |
754 | if (sdata) { | 773 | if (sdata) { |
755 | ieee80211_vif_release_channel(sdata); | 774 | ieee80211_vif_release_channel(sdata); |
756 | ret = ieee80211_vif_use_channel( | 775 | ret = ieee80211_vif_use_channel(sdata, chandef, |
757 | sdata, chan, channel_type, | ||
758 | IEEE80211_CHANCTX_EXCLUSIVE); | 776 | IEEE80211_CHANCTX_EXCLUSIVE); |
759 | } | 777 | } |
760 | } else if (local->open_count == local->monitors) { | 778 | } else if (local->open_count == local->monitors) { |
761 | local->_oper_channel = chan; | 779 | local->_oper_channel = chandef->chan; |
762 | local->_oper_channel_type = channel_type; | 780 | local->_oper_channel_type = cfg80211_get_chandef_type(chandef); |
763 | ieee80211_hw_config(local, 0); | 781 | ieee80211_hw_config(local, 0); |
764 | } | 782 | } |
765 | 783 | ||
766 | if (ret == 0) { | 784 | if (ret == 0) |
767 | local->monitor_channel = chan; | 785 | local->monitor_chandef = *chandef; |
768 | local->monitor_channel_type = channel_type; | ||
769 | } | ||
770 | mutex_unlock(&local->iflist_mtx); | 786 | mutex_unlock(&local->iflist_mtx); |
771 | 787 | ||
772 | return ret; | 788 | return ret; |
@@ -888,8 +904,7 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev, | |||
888 | sdata->smps_mode = IEEE80211_SMPS_OFF; | 904 | sdata->smps_mode = IEEE80211_SMPS_OFF; |
889 | sdata->needed_rx_chains = sdata->local->rx_chains; | 905 | sdata->needed_rx_chains = sdata->local->rx_chains; |
890 | 906 | ||
891 | err = ieee80211_vif_use_channel(sdata, params->channel, | 907 | err = ieee80211_vif_use_channel(sdata, ¶ms->chandef, |
892 | params->channel_type, | ||
893 | IEEE80211_CHANCTX_SHARED); | 908 | IEEE80211_CHANCTX_SHARED); |
894 | if (err) | 909 | if (err) |
895 | return err; | 910 | return err; |
@@ -1707,8 +1722,7 @@ static int ieee80211_join_mesh(struct wiphy *wiphy, struct net_device *dev, | |||
1707 | sdata->smps_mode = IEEE80211_SMPS_OFF; | 1722 | sdata->smps_mode = IEEE80211_SMPS_OFF; |
1708 | sdata->needed_rx_chains = sdata->local->rx_chains; | 1723 | sdata->needed_rx_chains = sdata->local->rx_chains; |
1709 | 1724 | ||
1710 | err = ieee80211_vif_use_channel(sdata, setup->channel, | 1725 | err = ieee80211_vif_use_channel(sdata, &setup->chandef, |
1711 | setup->channel_type, | ||
1712 | IEEE80211_CHANCTX_SHARED); | 1726 | IEEE80211_CHANCTX_SHARED); |
1713 | if (err) | 1727 | if (err) |
1714 | return err; | 1728 | return err; |
@@ -1990,10 +2004,16 @@ static int ieee80211_set_wiphy_params(struct wiphy *wiphy, u32 changed) | |||
1990 | return err; | 2004 | return err; |
1991 | } | 2005 | } |
1992 | 2006 | ||
1993 | if (changed & WIPHY_PARAM_RETRY_SHORT) | 2007 | if (changed & WIPHY_PARAM_RETRY_SHORT) { |
2008 | if (wiphy->retry_short > IEEE80211_MAX_TX_RETRY) | ||
2009 | return -EINVAL; | ||
1994 | local->hw.conf.short_frame_max_tx_count = wiphy->retry_short; | 2010 | local->hw.conf.short_frame_max_tx_count = wiphy->retry_short; |
1995 | if (changed & WIPHY_PARAM_RETRY_LONG) | 2011 | } |
2012 | if (changed & WIPHY_PARAM_RETRY_LONG) { | ||
2013 | if (wiphy->retry_long > IEEE80211_MAX_TX_RETRY) | ||
2014 | return -EINVAL; | ||
1996 | local->hw.conf.long_frame_max_tx_count = wiphy->retry_long; | 2015 | local->hw.conf.long_frame_max_tx_count = wiphy->retry_long; |
2016 | } | ||
1997 | if (changed & | 2017 | if (changed & |
1998 | (WIPHY_PARAM_RETRY_SHORT | WIPHY_PARAM_RETRY_LONG)) | 2018 | (WIPHY_PARAM_RETRY_SHORT | WIPHY_PARAM_RETRY_LONG)) |
1999 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_RETRY_LIMITS); | 2019 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_RETRY_LIMITS); |
@@ -2129,7 +2149,7 @@ int __ieee80211_request_smps(struct ieee80211_sub_if_data *sdata, | |||
2129 | * the new value until we associate. | 2149 | * the new value until we associate. |
2130 | */ | 2150 | */ |
2131 | if (!sdata->u.mgd.associated || | 2151 | if (!sdata->u.mgd.associated || |
2132 | sdata->vif.bss_conf.channel_type == NL80211_CHAN_NO_HT) | 2152 | sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT) |
2133 | return 0; | 2153 | return 0; |
2134 | 2154 | ||
2135 | ap = sdata->u.mgd.associated->bssid; | 2155 | ap = sdata->u.mgd.associated->bssid; |
@@ -2236,7 +2256,6 @@ static int ieee80211_set_bitrate_mask(struct wiphy *wiphy, | |||
2236 | static int ieee80211_start_roc_work(struct ieee80211_local *local, | 2256 | static int ieee80211_start_roc_work(struct ieee80211_local *local, |
2237 | struct ieee80211_sub_if_data *sdata, | 2257 | struct ieee80211_sub_if_data *sdata, |
2238 | struct ieee80211_channel *channel, | 2258 | struct ieee80211_channel *channel, |
2239 | enum nl80211_channel_type channel_type, | ||
2240 | unsigned int duration, u64 *cookie, | 2259 | unsigned int duration, u64 *cookie, |
2241 | struct sk_buff *txskb) | 2260 | struct sk_buff *txskb) |
2242 | { | 2261 | { |
@@ -2254,7 +2273,6 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local, | |||
2254 | return -ENOMEM; | 2273 | return -ENOMEM; |
2255 | 2274 | ||
2256 | roc->chan = channel; | 2275 | roc->chan = channel; |
2257 | roc->chan_type = channel_type; | ||
2258 | roc->duration = duration; | 2276 | roc->duration = duration; |
2259 | roc->req_duration = duration; | 2277 | roc->req_duration = duration; |
2260 | roc->frame = txskb; | 2278 | roc->frame = txskb; |
@@ -2287,8 +2305,7 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local, | |||
2287 | if (!duration) | 2305 | if (!duration) |
2288 | duration = 10; | 2306 | duration = 10; |
2289 | 2307 | ||
2290 | ret = drv_remain_on_channel(local, sdata, channel, channel_type, | 2308 | ret = drv_remain_on_channel(local, sdata, channel, duration); |
2291 | duration); | ||
2292 | if (ret) { | 2309 | if (ret) { |
2293 | kfree(roc); | 2310 | kfree(roc); |
2294 | return ret; | 2311 | return ret; |
@@ -2299,8 +2316,7 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local, | |||
2299 | 2316 | ||
2300 | out_check_combine: | 2317 | out_check_combine: |
2301 | list_for_each_entry(tmp, &local->roc_list, list) { | 2318 | list_for_each_entry(tmp, &local->roc_list, list) { |
2302 | if (tmp->chan != channel || tmp->chan_type != channel_type || | 2319 | if (tmp->chan != channel || tmp->sdata != sdata) |
2303 | tmp->sdata != sdata) | ||
2304 | continue; | 2320 | continue; |
2305 | 2321 | ||
2306 | /* | 2322 | /* |
@@ -2417,7 +2433,6 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local, | |||
2417 | static int ieee80211_remain_on_channel(struct wiphy *wiphy, | 2433 | static int ieee80211_remain_on_channel(struct wiphy *wiphy, |
2418 | struct wireless_dev *wdev, | 2434 | struct wireless_dev *wdev, |
2419 | struct ieee80211_channel *chan, | 2435 | struct ieee80211_channel *chan, |
2420 | enum nl80211_channel_type channel_type, | ||
2421 | unsigned int duration, | 2436 | unsigned int duration, |
2422 | u64 *cookie) | 2437 | u64 *cookie) |
2423 | { | 2438 | { |
@@ -2426,7 +2441,7 @@ static int ieee80211_remain_on_channel(struct wiphy *wiphy, | |||
2426 | int ret; | 2441 | int ret; |
2427 | 2442 | ||
2428 | mutex_lock(&local->mtx); | 2443 | mutex_lock(&local->mtx); |
2429 | ret = ieee80211_start_roc_work(local, sdata, chan, channel_type, | 2444 | ret = ieee80211_start_roc_work(local, sdata, chan, |
2430 | duration, cookie, NULL); | 2445 | duration, cookie, NULL); |
2431 | mutex_unlock(&local->mtx); | 2446 | mutex_unlock(&local->mtx); |
2432 | 2447 | ||
@@ -2519,10 +2534,8 @@ static int ieee80211_cancel_remain_on_channel(struct wiphy *wiphy, | |||
2519 | 2534 | ||
2520 | static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, | 2535 | static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, |
2521 | struct ieee80211_channel *chan, bool offchan, | 2536 | struct ieee80211_channel *chan, bool offchan, |
2522 | enum nl80211_channel_type channel_type, | 2537 | unsigned int wait, const u8 *buf, size_t len, |
2523 | bool channel_type_valid, unsigned int wait, | 2538 | bool no_cck, bool dont_wait_for_ack, u64 *cookie) |
2524 | const u8 *buf, size_t len, bool no_cck, | ||
2525 | bool dont_wait_for_ack, u64 *cookie) | ||
2526 | { | 2539 | { |
2527 | struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev); | 2540 | struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev); |
2528 | struct ieee80211_local *local = sdata->local; | 2541 | struct ieee80211_local *local = sdata->local; |
@@ -2591,14 +2604,10 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, | |||
2591 | rcu_read_lock(); | 2604 | rcu_read_lock(); |
2592 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); | 2605 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); |
2593 | 2606 | ||
2594 | if (chanctx_conf) { | 2607 | if (chanctx_conf) |
2595 | need_offchan = chan != chanctx_conf->channel; | 2608 | need_offchan = chan != chanctx_conf->def.chan; |
2596 | if (channel_type_valid && | 2609 | else |
2597 | channel_type != chanctx_conf->channel_type) | ||
2598 | need_offchan = true; | ||
2599 | } else { | ||
2600 | need_offchan = true; | 2610 | need_offchan = true; |
2601 | } | ||
2602 | rcu_read_unlock(); | 2611 | rcu_read_unlock(); |
2603 | } | 2612 | } |
2604 | 2613 | ||
@@ -2633,7 +2642,7 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, | |||
2633 | local->hw.offchannel_tx_hw_queue; | 2642 | local->hw.offchannel_tx_hw_queue; |
2634 | 2643 | ||
2635 | /* This will handle all kinds of coalescing and immediate TX */ | 2644 | /* This will handle all kinds of coalescing and immediate TX */ |
2636 | ret = ieee80211_start_roc_work(local, sdata, chan, channel_type, | 2645 | ret = ieee80211_start_roc_work(local, sdata, chan, |
2637 | wait, cookie, skb); | 2646 | wait, cookie, skb); |
2638 | if (ret) | 2647 | if (ret) |
2639 | kfree_skb(skb); | 2648 | kfree_skb(skb); |
@@ -3067,7 +3076,7 @@ static int ieee80211_probe_client(struct wiphy *wiphy, struct net_device *dev, | |||
3067 | rcu_read_unlock(); | 3076 | rcu_read_unlock(); |
3068 | return -EINVAL; | 3077 | return -EINVAL; |
3069 | } | 3078 | } |
3070 | band = chanctx_conf->channel->band; | 3079 | band = chanctx_conf->def.chan->band; |
3071 | sta = sta_info_get(sdata, peer); | 3080 | sta = sta_info_get(sdata, peer); |
3072 | if (sta) { | 3081 | if (sta) { |
3073 | qos = test_sta_flag(sta, WLAN_STA_WME); | 3082 | qos = test_sta_flag(sta, WLAN_STA_WME); |
@@ -3124,23 +3133,23 @@ static int ieee80211_probe_client(struct wiphy *wiphy, struct net_device *dev, | |||
3124 | return 0; | 3133 | return 0; |
3125 | } | 3134 | } |
3126 | 3135 | ||
3127 | static struct ieee80211_channel * | 3136 | static int ieee80211_cfg_get_channel(struct wiphy *wiphy, |
3128 | ieee80211_cfg_get_channel(struct wiphy *wiphy, struct wireless_dev *wdev, | 3137 | struct wireless_dev *wdev, |
3129 | enum nl80211_channel_type *type) | 3138 | struct cfg80211_chan_def *chandef) |
3130 | { | 3139 | { |
3131 | struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev); | 3140 | struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev); |
3132 | struct ieee80211_chanctx_conf *chanctx_conf; | 3141 | struct ieee80211_chanctx_conf *chanctx_conf; |
3133 | struct ieee80211_channel *chan = NULL; | 3142 | int ret = -ENODATA; |
3134 | 3143 | ||
3135 | rcu_read_lock(); | 3144 | rcu_read_lock(); |
3136 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); | 3145 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); |
3137 | if (chanctx_conf) { | 3146 | if (chanctx_conf) { |
3138 | *type = chanctx_conf->channel_type; | 3147 | *chandef = chanctx_conf->def; |
3139 | chan = chanctx_conf->channel; | 3148 | ret = 0; |
3140 | } | 3149 | } |
3141 | rcu_read_unlock(); | 3150 | rcu_read_unlock(); |
3142 | 3151 | ||
3143 | return chan; | 3152 | return ret; |
3144 | } | 3153 | } |
3145 | 3154 | ||
3146 | #ifdef CONFIG_PM | 3155 | #ifdef CONFIG_PM |
diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c index a2b06d40aebf..53f03120db55 100644 --- a/net/mac80211/chan.c +++ b/net/mac80211/chan.c | |||
@@ -8,93 +8,47 @@ | |||
8 | #include "ieee80211_i.h" | 8 | #include "ieee80211_i.h" |
9 | #include "driver-ops.h" | 9 | #include "driver-ops.h" |
10 | 10 | ||
11 | static bool | 11 | static void ieee80211_change_chandef(struct ieee80211_local *local, |
12 | ieee80211_channel_types_are_compatible(enum nl80211_channel_type chantype1, | 12 | struct ieee80211_chanctx *ctx, |
13 | enum nl80211_channel_type chantype2, | 13 | const struct cfg80211_chan_def *chandef) |
14 | enum nl80211_channel_type *compat) | ||
15 | { | 14 | { |
16 | /* | 15 | if (cfg80211_chandef_identical(&ctx->conf.def, chandef)) |
17 | * start out with chantype1 being the result, | ||
18 | * overwriting later if needed | ||
19 | */ | ||
20 | if (compat) | ||
21 | *compat = chantype1; | ||
22 | |||
23 | switch (chantype1) { | ||
24 | case NL80211_CHAN_NO_HT: | ||
25 | if (compat) | ||
26 | *compat = chantype2; | ||
27 | break; | ||
28 | case NL80211_CHAN_HT20: | ||
29 | /* | ||
30 | * allow any change that doesn't go to no-HT | ||
31 | * (if it already is no-HT no change is needed) | ||
32 | */ | ||
33 | if (chantype2 == NL80211_CHAN_NO_HT) | ||
34 | break; | ||
35 | if (compat) | ||
36 | *compat = chantype2; | ||
37 | break; | ||
38 | case NL80211_CHAN_HT40PLUS: | ||
39 | case NL80211_CHAN_HT40MINUS: | ||
40 | /* allow smaller bandwidth and same */ | ||
41 | if (chantype2 == NL80211_CHAN_NO_HT) | ||
42 | break; | ||
43 | if (chantype2 == NL80211_CHAN_HT20) | ||
44 | break; | ||
45 | if (chantype2 == chantype1) | ||
46 | break; | ||
47 | return false; | ||
48 | } | ||
49 | |||
50 | return true; | ||
51 | } | ||
52 | |||
53 | static void ieee80211_change_chantype(struct ieee80211_local *local, | ||
54 | struct ieee80211_chanctx *ctx, | ||
55 | enum nl80211_channel_type chantype) | ||
56 | { | ||
57 | if (chantype == ctx->conf.channel_type) | ||
58 | return; | 16 | return; |
59 | 17 | ||
60 | ctx->conf.channel_type = chantype; | 18 | WARN_ON(!cfg80211_chandef_compatible(&ctx->conf.def, chandef)); |
61 | drv_change_chanctx(local, ctx, IEEE80211_CHANCTX_CHANGE_CHANNEL_TYPE); | 19 | |
20 | ctx->conf.def = *chandef; | ||
21 | drv_change_chanctx(local, ctx, IEEE80211_CHANCTX_CHANGE_WIDTH); | ||
62 | 22 | ||
63 | if (!local->use_chanctx) { | 23 | if (!local->use_chanctx) { |
64 | local->_oper_channel_type = chantype; | 24 | local->_oper_channel_type = cfg80211_get_chandef_type(chandef); |
65 | ieee80211_hw_config(local, 0); | 25 | ieee80211_hw_config(local, 0); |
66 | } | 26 | } |
67 | } | 27 | } |
68 | 28 | ||
69 | static struct ieee80211_chanctx * | 29 | static struct ieee80211_chanctx * |
70 | ieee80211_find_chanctx(struct ieee80211_local *local, | 30 | ieee80211_find_chanctx(struct ieee80211_local *local, |
71 | struct ieee80211_channel *channel, | 31 | const struct cfg80211_chan_def *chandef, |
72 | enum nl80211_channel_type channel_type, | ||
73 | enum ieee80211_chanctx_mode mode) | 32 | enum ieee80211_chanctx_mode mode) |
74 | { | 33 | { |
75 | struct ieee80211_chanctx *ctx; | 34 | struct ieee80211_chanctx *ctx; |
76 | enum nl80211_channel_type compat_type; | ||
77 | 35 | ||
78 | lockdep_assert_held(&local->chanctx_mtx); | 36 | lockdep_assert_held(&local->chanctx_mtx); |
79 | 37 | ||
80 | if (mode == IEEE80211_CHANCTX_EXCLUSIVE) | 38 | if (mode == IEEE80211_CHANCTX_EXCLUSIVE) |
81 | return NULL; | 39 | return NULL; |
82 | if (WARN_ON(!channel)) | ||
83 | return NULL; | ||
84 | 40 | ||
85 | list_for_each_entry(ctx, &local->chanctx_list, list) { | 41 | list_for_each_entry(ctx, &local->chanctx_list, list) { |
86 | compat_type = ctx->conf.channel_type; | 42 | const struct cfg80211_chan_def *compat; |
87 | 43 | ||
88 | if (ctx->mode == IEEE80211_CHANCTX_EXCLUSIVE) | 44 | if (ctx->mode == IEEE80211_CHANCTX_EXCLUSIVE) |
89 | continue; | 45 | continue; |
90 | if (ctx->conf.channel != channel) | 46 | |
91 | continue; | 47 | compat = cfg80211_chandef_compatible(&ctx->conf.def, chandef); |
92 | if (!ieee80211_channel_types_are_compatible(ctx->conf.channel_type, | 48 | if (!compat) |
93 | channel_type, | ||
94 | &compat_type)) | ||
95 | continue; | 49 | continue; |
96 | 50 | ||
97 | ieee80211_change_chantype(local, ctx, compat_type); | 51 | ieee80211_change_chandef(local, ctx, compat); |
98 | 52 | ||
99 | return ctx; | 53 | return ctx; |
100 | } | 54 | } |
@@ -104,8 +58,7 @@ ieee80211_find_chanctx(struct ieee80211_local *local, | |||
104 | 58 | ||
105 | static struct ieee80211_chanctx * | 59 | static struct ieee80211_chanctx * |
106 | ieee80211_new_chanctx(struct ieee80211_local *local, | 60 | ieee80211_new_chanctx(struct ieee80211_local *local, |
107 | struct ieee80211_channel *channel, | 61 | const struct cfg80211_chan_def *chandef, |
108 | enum nl80211_channel_type channel_type, | ||
109 | enum ieee80211_chanctx_mode mode) | 62 | enum ieee80211_chanctx_mode mode) |
110 | { | 63 | { |
111 | struct ieee80211_chanctx *ctx; | 64 | struct ieee80211_chanctx *ctx; |
@@ -117,15 +70,15 @@ ieee80211_new_chanctx(struct ieee80211_local *local, | |||
117 | if (!ctx) | 70 | if (!ctx) |
118 | return ERR_PTR(-ENOMEM); | 71 | return ERR_PTR(-ENOMEM); |
119 | 72 | ||
120 | ctx->conf.channel = channel; | 73 | ctx->conf.def = *chandef; |
121 | ctx->conf.channel_type = channel_type; | ||
122 | ctx->conf.rx_chains_static = 1; | 74 | ctx->conf.rx_chains_static = 1; |
123 | ctx->conf.rx_chains_dynamic = 1; | 75 | ctx->conf.rx_chains_dynamic = 1; |
124 | ctx->mode = mode; | 76 | ctx->mode = mode; |
125 | 77 | ||
126 | if (!local->use_chanctx) { | 78 | if (!local->use_chanctx) { |
127 | local->_oper_channel_type = channel_type; | 79 | local->_oper_channel_type = |
128 | local->_oper_channel = channel; | 80 | cfg80211_get_chandef_type(chandef); |
81 | local->_oper_channel = chandef->chan; | ||
129 | ieee80211_hw_config(local, 0); | 82 | ieee80211_hw_config(local, 0); |
130 | } else { | 83 | } else { |
131 | err = drv_add_chanctx(local, ctx); | 84 | err = drv_add_chanctx(local, ctx); |
@@ -178,41 +131,37 @@ static int ieee80211_assign_vif_chanctx(struct ieee80211_sub_if_data *sdata, | |||
178 | return 0; | 131 | return 0; |
179 | } | 132 | } |
180 | 133 | ||
181 | static enum nl80211_channel_type | 134 | static void ieee80211_recalc_chanctx_chantype(struct ieee80211_local *local, |
182 | ieee80211_calc_chantype(struct ieee80211_local *local, | 135 | struct ieee80211_chanctx *ctx) |
183 | struct ieee80211_chanctx *ctx) | ||
184 | { | 136 | { |
185 | struct ieee80211_chanctx_conf *conf = &ctx->conf; | 137 | struct ieee80211_chanctx_conf *conf = &ctx->conf; |
186 | struct ieee80211_sub_if_data *sdata; | 138 | struct ieee80211_sub_if_data *sdata; |
187 | enum nl80211_channel_type result = NL80211_CHAN_NO_HT; | 139 | const struct cfg80211_chan_def *compat = NULL; |
188 | 140 | ||
189 | lockdep_assert_held(&local->chanctx_mtx); | 141 | lockdep_assert_held(&local->chanctx_mtx); |
190 | 142 | ||
191 | rcu_read_lock(); | 143 | rcu_read_lock(); |
192 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { | 144 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { |
145 | |||
193 | if (!ieee80211_sdata_running(sdata)) | 146 | if (!ieee80211_sdata_running(sdata)) |
194 | continue; | 147 | continue; |
195 | if (rcu_access_pointer(sdata->vif.chanctx_conf) != conf) | 148 | if (rcu_access_pointer(sdata->vif.chanctx_conf) != conf) |
196 | continue; | 149 | continue; |
197 | 150 | ||
198 | WARN_ON_ONCE(!ieee80211_channel_types_are_compatible( | 151 | if (!compat) |
199 | sdata->vif.bss_conf.channel_type, | 152 | compat = &sdata->vif.bss_conf.chandef; |
200 | result, &result)); | 153 | |
154 | compat = cfg80211_chandef_compatible( | ||
155 | &sdata->vif.bss_conf.chandef, compat); | ||
156 | if (!compat) | ||
157 | break; | ||
201 | } | 158 | } |
202 | rcu_read_unlock(); | 159 | rcu_read_unlock(); |
203 | 160 | ||
204 | return result; | 161 | if (WARN_ON_ONCE(!compat)) |
205 | } | 162 | return; |
206 | |||
207 | static void ieee80211_recalc_chanctx_chantype(struct ieee80211_local *local, | ||
208 | struct ieee80211_chanctx *ctx) | ||
209 | { | ||
210 | enum nl80211_channel_type chantype; | ||
211 | |||
212 | lockdep_assert_held(&local->chanctx_mtx); | ||
213 | 163 | ||
214 | chantype = ieee80211_calc_chantype(local, ctx); | 164 | ieee80211_change_chandef(local, ctx, compat); |
215 | ieee80211_change_chantype(local, ctx, chantype); | ||
216 | } | 165 | } |
217 | 166 | ||
218 | static void ieee80211_unassign_vif_chanctx(struct ieee80211_sub_if_data *sdata, | 167 | static void ieee80211_unassign_vif_chanctx(struct ieee80211_sub_if_data *sdata, |
@@ -337,8 +286,7 @@ void ieee80211_recalc_smps_chanctx(struct ieee80211_local *local, | |||
337 | } | 286 | } |
338 | 287 | ||
339 | int ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata, | 288 | int ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata, |
340 | struct ieee80211_channel *channel, | 289 | const struct cfg80211_chan_def *chandef, |
341 | enum nl80211_channel_type channel_type, | ||
342 | enum ieee80211_chanctx_mode mode) | 290 | enum ieee80211_chanctx_mode mode) |
343 | { | 291 | { |
344 | struct ieee80211_local *local = sdata->local; | 292 | struct ieee80211_local *local = sdata->local; |
@@ -350,15 +298,15 @@ int ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata, | |||
350 | mutex_lock(&local->chanctx_mtx); | 298 | mutex_lock(&local->chanctx_mtx); |
351 | __ieee80211_vif_release_channel(sdata); | 299 | __ieee80211_vif_release_channel(sdata); |
352 | 300 | ||
353 | ctx = ieee80211_find_chanctx(local, channel, channel_type, mode); | 301 | ctx = ieee80211_find_chanctx(local, chandef, mode); |
354 | if (!ctx) | 302 | if (!ctx) |
355 | ctx = ieee80211_new_chanctx(local, channel, channel_type, mode); | 303 | ctx = ieee80211_new_chanctx(local, chandef, mode); |
356 | if (IS_ERR(ctx)) { | 304 | if (IS_ERR(ctx)) { |
357 | ret = PTR_ERR(ctx); | 305 | ret = PTR_ERR(ctx); |
358 | goto out; | 306 | goto out; |
359 | } | 307 | } |
360 | 308 | ||
361 | sdata->vif.bss_conf.channel_type = channel_type; | 309 | sdata->vif.bss_conf.chandef = *chandef; |
362 | 310 | ||
363 | ret = ieee80211_assign_vif_chanctx(sdata, ctx); | 311 | ret = ieee80211_assign_vif_chanctx(sdata, ctx); |
364 | if (ret) { | 312 | if (ret) { |
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c index ba9bd0ef119a..cbde5cc49a40 100644 --- a/net/mac80211/debugfs_netdev.c +++ b/net/mac80211/debugfs_netdev.c | |||
@@ -168,7 +168,6 @@ IEEE80211_IF_FILE(rc_rateidx_mcs_mask_5ghz, | |||
168 | 168 | ||
169 | IEEE80211_IF_FILE(flags, flags, HEX); | 169 | IEEE80211_IF_FILE(flags, flags, HEX); |
170 | IEEE80211_IF_FILE(state, state, LHEX); | 170 | IEEE80211_IF_FILE(state, state, LHEX); |
171 | IEEE80211_IF_FILE(channel_type, vif.bss_conf.channel_type, DEC); | ||
172 | IEEE80211_IF_FILE(txpower, vif.bss_conf.txpower, DEC); | 171 | IEEE80211_IF_FILE(txpower, vif.bss_conf.txpower, DEC); |
173 | IEEE80211_IF_FILE(ap_power_level, ap_power_level, DEC); | 172 | IEEE80211_IF_FILE(ap_power_level, ap_power_level, DEC); |
174 | IEEE80211_IF_FILE(user_power_level, user_power_level, DEC); | 173 | IEEE80211_IF_FILE(user_power_level, user_power_level, DEC); |
@@ -632,7 +631,6 @@ static void add_files(struct ieee80211_sub_if_data *sdata) | |||
632 | 631 | ||
633 | DEBUGFS_ADD(flags); | 632 | DEBUGFS_ADD(flags); |
634 | DEBUGFS_ADD(state); | 633 | DEBUGFS_ADD(state); |
635 | DEBUGFS_ADD(channel_type); | ||
636 | DEBUGFS_ADD(txpower); | 634 | DEBUGFS_ADD(txpower); |
637 | DEBUGFS_ADD(user_power_level); | 635 | DEBUGFS_ADD(user_power_level); |
638 | DEBUGFS_ADD(ap_power_level); | 636 | DEBUGFS_ADD(ap_power_level); |
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index 68c27aaf5c93..c6560cc7a9d6 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h | |||
@@ -738,16 +738,15 @@ static inline int drv_get_antenna(struct ieee80211_local *local, | |||
738 | static inline int drv_remain_on_channel(struct ieee80211_local *local, | 738 | static inline int drv_remain_on_channel(struct ieee80211_local *local, |
739 | struct ieee80211_sub_if_data *sdata, | 739 | struct ieee80211_sub_if_data *sdata, |
740 | struct ieee80211_channel *chan, | 740 | struct ieee80211_channel *chan, |
741 | enum nl80211_channel_type chantype, | ||
742 | unsigned int duration) | 741 | unsigned int duration) |
743 | { | 742 | { |
744 | int ret; | 743 | int ret; |
745 | 744 | ||
746 | might_sleep(); | 745 | might_sleep(); |
747 | 746 | ||
748 | trace_drv_remain_on_channel(local, sdata, chan, chantype, duration); | 747 | trace_drv_remain_on_channel(local, sdata, chan, duration); |
749 | ret = local->ops->remain_on_channel(&local->hw, &sdata->vif, | 748 | ret = local->ops->remain_on_channel(&local->hw, &sdata->vif, |
750 | chan, chantype, duration); | 749 | chan, duration); |
751 | trace_drv_return_int(local, ret); | 750 | trace_drv_return_int(local, ret); |
752 | 751 | ||
753 | return ret; | 752 | return ret; |
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index 7aa02da52125..fa862b24a7e0 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c | |||
@@ -51,7 +51,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
51 | struct cfg80211_bss *bss; | 51 | struct cfg80211_bss *bss; |
52 | u32 bss_change; | 52 | u32 bss_change; |
53 | u8 supp_rates[IEEE80211_MAX_SUPP_RATES]; | 53 | u8 supp_rates[IEEE80211_MAX_SUPP_RATES]; |
54 | enum nl80211_channel_type channel_type; | 54 | struct cfg80211_chan_def chandef; |
55 | 55 | ||
56 | lockdep_assert_held(&ifibss->mtx); | 56 | lockdep_assert_held(&ifibss->mtx); |
57 | 57 | ||
@@ -79,12 +79,14 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
79 | 79 | ||
80 | sdata->drop_unencrypted = capability & WLAN_CAPABILITY_PRIVACY ? 1 : 0; | 80 | sdata->drop_unencrypted = capability & WLAN_CAPABILITY_PRIVACY ? 1 : 0; |
81 | 81 | ||
82 | channel_type = ifibss->channel_type; | 82 | cfg80211_chandef_create(&chandef, chan, ifibss->channel_type); |
83 | if (!cfg80211_can_beacon_sec_chan(local->hw.wiphy, chan, channel_type)) | 83 | if (!cfg80211_reg_can_beacon(local->hw.wiphy, &chandef)) { |
84 | channel_type = NL80211_CHAN_HT20; | 84 | chandef.width = NL80211_CHAN_WIDTH_20; |
85 | chandef.center_freq1 = chan->center_freq; | ||
86 | } | ||
85 | 87 | ||
86 | ieee80211_vif_release_channel(sdata); | 88 | ieee80211_vif_release_channel(sdata); |
87 | if (ieee80211_vif_use_channel(sdata, chan, channel_type, | 89 | if (ieee80211_vif_use_channel(sdata, &chandef, |
88 | ifibss->fixed_channel ? | 90 | ifibss->fixed_channel ? |
89 | IEEE80211_CHANCTX_SHARED : | 91 | IEEE80211_CHANCTX_SHARED : |
90 | IEEE80211_CHANCTX_EXCLUSIVE)) { | 92 | IEEE80211_CHANCTX_EXCLUSIVE)) { |
@@ -158,7 +160,8 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
158 | ifibss->ie, ifibss->ie_len); | 160 | ifibss->ie, ifibss->ie_len); |
159 | 161 | ||
160 | /* add HT capability and information IEs */ | 162 | /* add HT capability and information IEs */ |
161 | if (channel_type && sband->ht_cap.ht_supported) { | 163 | if (chandef.width != NL80211_CHAN_WIDTH_20_NOHT && |
164 | sband->ht_cap.ht_supported) { | ||
162 | pos = skb_put(skb, 4 + | 165 | pos = skb_put(skb, 4 + |
163 | sizeof(struct ieee80211_ht_cap) + | 166 | sizeof(struct ieee80211_ht_cap) + |
164 | sizeof(struct ieee80211_ht_operation)); | 167 | sizeof(struct ieee80211_ht_operation)); |
@@ -170,7 +173,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
170 | * keep them at 0 | 173 | * keep them at 0 |
171 | */ | 174 | */ |
172 | pos = ieee80211_ie_build_ht_oper(pos, &sband->ht_cap, | 175 | pos = ieee80211_ie_build_ht_oper(pos, &sband->ht_cap, |
173 | chan, channel_type, 0); | 176 | &chandef, 0); |
174 | } | 177 | } |
175 | 178 | ||
176 | if (local->hw.queues >= IEEE80211_NUM_ACS) { | 179 | if (local->hw.queues >= IEEE80211_NUM_ACS) { |
@@ -326,7 +329,7 @@ ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, | |||
326 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); | 329 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); |
327 | if (WARN_ON_ONCE(!chanctx_conf)) | 330 | if (WARN_ON_ONCE(!chanctx_conf)) |
328 | return NULL; | 331 | return NULL; |
329 | band = chanctx_conf->channel->band; | 332 | band = chanctx_conf->def.chan->band; |
330 | rcu_read_unlock(); | 333 | rcu_read_unlock(); |
331 | 334 | ||
332 | sta = sta_info_alloc(sdata, addr, GFP_KERNEL); | 335 | sta = sta_info_alloc(sdata, addr, GFP_KERNEL); |
@@ -374,11 +377,13 @@ static void ieee80211_rx_mgmt_auth_ibss(struct ieee80211_sub_if_data *sdata, | |||
374 | auth_alg = le16_to_cpu(mgmt->u.auth.auth_alg); | 377 | auth_alg = le16_to_cpu(mgmt->u.auth.auth_alg); |
375 | auth_transaction = le16_to_cpu(mgmt->u.auth.auth_transaction); | 378 | auth_transaction = le16_to_cpu(mgmt->u.auth.auth_transaction); |
376 | 379 | ||
377 | if (auth_alg != WLAN_AUTH_OPEN || auth_transaction != 1) | ||
378 | return; | ||
379 | ibss_dbg(sdata, | 380 | ibss_dbg(sdata, |
380 | "RX Auth SA=%pM DA=%pM BSSID=%pM (auth_transaction=%d)\n", | 381 | "RX Auth SA=%pM DA=%pM BSSID=%pM (auth_transaction=%d)\n", |
381 | mgmt->sa, mgmt->da, mgmt->bssid, auth_transaction); | 382 | mgmt->sa, mgmt->da, mgmt->bssid, auth_transaction); |
383 | |||
384 | if (auth_alg != WLAN_AUTH_OPEN || auth_transaction != 1) | ||
385 | return; | ||
386 | |||
382 | sta_info_destroy_addr(sdata, mgmt->sa); | 387 | sta_info_destroy_addr(sdata, mgmt->sa); |
383 | sta = ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa, 0, false); | 388 | sta = ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa, 0, false); |
384 | rcu_read_unlock(); | 389 | rcu_read_unlock(); |
@@ -473,9 +478,11 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
473 | sdata->u.ibss.channel_type != NL80211_CHAN_NO_HT) { | 478 | sdata->u.ibss.channel_type != NL80211_CHAN_NO_HT) { |
474 | /* we both use HT */ | 479 | /* we both use HT */ |
475 | struct ieee80211_sta_ht_cap sta_ht_cap_new; | 480 | struct ieee80211_sta_ht_cap sta_ht_cap_new; |
476 | enum nl80211_channel_type channel_type = | 481 | struct cfg80211_chan_def chandef; |
477 | ieee80211_ht_oper_to_channel_type( | 482 | |
478 | elems->ht_operation); | 483 | ieee80211_ht_oper_to_chandef(channel, |
484 | elems->ht_operation, | ||
485 | &chandef); | ||
479 | 486 | ||
480 | ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband, | 487 | ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband, |
481 | elems->ht_cap_elem, | 488 | elems->ht_cap_elem, |
@@ -485,9 +492,9 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
485 | * fall back to HT20 if we don't use or use | 492 | * fall back to HT20 if we don't use or use |
486 | * the other extension channel | 493 | * the other extension channel |
487 | */ | 494 | */ |
488 | if (!(channel_type == NL80211_CHAN_HT40MINUS || | 495 | if (chandef.width != NL80211_CHAN_WIDTH_40 || |
489 | channel_type == NL80211_CHAN_HT40PLUS) || | 496 | cfg80211_get_chandef_type(&chandef) != |
490 | channel_type != sdata->u.ibss.channel_type) | 497 | sdata->u.ibss.channel_type) |
491 | sta_ht_cap_new.cap &= | 498 | sta_ht_cap_new.cap &= |
492 | ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; | 499 | ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; |
493 | 500 | ||
@@ -611,7 +618,7 @@ void ieee80211_ibss_rx_no_sta(struct ieee80211_sub_if_data *sdata, | |||
611 | rcu_read_unlock(); | 618 | rcu_read_unlock(); |
612 | return; | 619 | return; |
613 | } | 620 | } |
614 | band = chanctx_conf->channel->band; | 621 | band = chanctx_conf->def.chan->band; |
615 | rcu_read_unlock(); | 622 | rcu_read_unlock(); |
616 | 623 | ||
617 | sta = sta_info_alloc(sdata, addr, GFP_ATOMIC); | 624 | sta = sta_info_alloc(sdata, addr, GFP_ATOMIC); |
@@ -1076,8 +1083,9 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata, | |||
1076 | 1083 | ||
1077 | sdata->vif.bss_conf.beacon_int = params->beacon_interval; | 1084 | sdata->vif.bss_conf.beacon_int = params->beacon_interval; |
1078 | 1085 | ||
1079 | sdata->u.ibss.channel = params->channel; | 1086 | sdata->u.ibss.channel = params->chandef.chan; |
1080 | sdata->u.ibss.channel_type = params->channel_type; | 1087 | sdata->u.ibss.channel_type = |
1088 | cfg80211_get_chandef_type(¶ms->chandef); | ||
1081 | sdata->u.ibss.fixed_channel = params->channel_fixed; | 1089 | sdata->u.ibss.fixed_channel = params->channel_fixed; |
1082 | 1090 | ||
1083 | if (params->ie) { | 1091 | if (params->ie) { |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 115117c558aa..5c0d5a6946c1 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -348,7 +348,6 @@ struct ieee80211_roc_work { | |||
348 | struct ieee80211_sub_if_data *sdata; | 348 | struct ieee80211_sub_if_data *sdata; |
349 | 349 | ||
350 | struct ieee80211_channel *chan; | 350 | struct ieee80211_channel *chan; |
351 | enum nl80211_channel_type chan_type; | ||
352 | 351 | ||
353 | bool started, abort, hw_begun, notified; | 352 | bool started, abort, hw_begun, notified; |
354 | 353 | ||
@@ -364,7 +363,7 @@ enum ieee80211_sta_flags { | |||
364 | IEEE80211_STA_BEACON_POLL = BIT(0), | 363 | IEEE80211_STA_BEACON_POLL = BIT(0), |
365 | IEEE80211_STA_CONNECTION_POLL = BIT(1), | 364 | IEEE80211_STA_CONNECTION_POLL = BIT(1), |
366 | IEEE80211_STA_CONTROL_PORT = BIT(2), | 365 | IEEE80211_STA_CONTROL_PORT = BIT(2), |
367 | IEEE80211_STA_DISABLE_11N = BIT(4), | 366 | IEEE80211_STA_DISABLE_HT = BIT(4), |
368 | IEEE80211_STA_CSA_RECEIVED = BIT(5), | 367 | IEEE80211_STA_CSA_RECEIVED = BIT(5), |
369 | IEEE80211_STA_MFP_ENABLED = BIT(6), | 368 | IEEE80211_STA_MFP_ENABLED = BIT(6), |
370 | IEEE80211_STA_UAPSD_ENABLED = BIT(7), | 369 | IEEE80211_STA_UAPSD_ENABLED = BIT(7), |
@@ -800,7 +799,7 @@ ieee80211_get_sdata_band(struct ieee80211_sub_if_data *sdata) | |||
800 | rcu_read_lock(); | 799 | rcu_read_lock(); |
801 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); | 800 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); |
802 | if (!WARN_ON(!chanctx_conf)) | 801 | if (!WARN_ON(!chanctx_conf)) |
803 | band = chanctx_conf->channel->band; | 802 | band = chanctx_conf->def.chan->band; |
804 | rcu_read_unlock(); | 803 | rcu_read_unlock(); |
805 | 804 | ||
806 | return band; | 805 | return band; |
@@ -1048,7 +1047,6 @@ struct ieee80211_local { | |||
1048 | 1047 | ||
1049 | /* Temporary remain-on-channel for off-channel operations */ | 1048 | /* Temporary remain-on-channel for off-channel operations */ |
1050 | struct ieee80211_channel *tmp_channel; | 1049 | struct ieee80211_channel *tmp_channel; |
1051 | enum nl80211_channel_type tmp_channel_type; | ||
1052 | 1050 | ||
1053 | /* channel contexts */ | 1051 | /* channel contexts */ |
1054 | struct list_head chanctx_list; | 1052 | struct list_head chanctx_list; |
@@ -1158,8 +1156,7 @@ struct ieee80211_local { | |||
1158 | 1156 | ||
1159 | /* virtual monitor interface */ | 1157 | /* virtual monitor interface */ |
1160 | struct ieee80211_sub_if_data __rcu *monitor_sdata; | 1158 | struct ieee80211_sub_if_data __rcu *monitor_sdata; |
1161 | struct ieee80211_channel *monitor_channel; | 1159 | struct cfg80211_chan_def monitor_chandef; |
1162 | enum nl80211_channel_type monitor_channel_type; | ||
1163 | }; | 1160 | }; |
1164 | 1161 | ||
1165 | static inline struct ieee80211_sub_if_data * | 1162 | static inline struct ieee80211_sub_if_data * |
@@ -1518,7 +1515,7 @@ static inline void ieee80211_tx_skb_tid(struct ieee80211_sub_if_data *sdata, | |||
1518 | } | 1515 | } |
1519 | 1516 | ||
1520 | __ieee80211_tx_skb_tid_band(sdata, skb, tid, | 1517 | __ieee80211_tx_skb_tid_band(sdata, skb, tid, |
1521 | chanctx_conf->channel->band); | 1518 | chanctx_conf->def.chan->band); |
1522 | rcu_read_unlock(); | 1519 | rcu_read_unlock(); |
1523 | } | 1520 | } |
1524 | 1521 | ||
@@ -1607,8 +1604,7 @@ size_t ieee80211_ie_split_vendor(const u8 *ies, size_t ielen, size_t offset); | |||
1607 | u8 *ieee80211_ie_build_ht_cap(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap, | 1604 | u8 *ieee80211_ie_build_ht_cap(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap, |
1608 | u16 cap); | 1605 | u16 cap); |
1609 | u8 *ieee80211_ie_build_ht_oper(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap, | 1606 | u8 *ieee80211_ie_build_ht_oper(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap, |
1610 | struct ieee80211_channel *channel, | 1607 | const struct cfg80211_chan_def *chandef, |
1611 | enum nl80211_channel_type channel_type, | ||
1612 | u16 prot_mode); | 1608 | u16 prot_mode); |
1613 | u8 *ieee80211_ie_build_vht_cap(u8 *pos, struct ieee80211_sta_vht_cap *vht_cap, | 1609 | u8 *ieee80211_ie_build_vht_cap(u8 *pos, struct ieee80211_sta_vht_cap *vht_cap, |
1614 | u32 cap); | 1610 | u32 cap); |
@@ -1620,13 +1616,13 @@ int ieee80211_add_ext_srates_ie(struct ieee80211_sub_if_data *sdata, | |||
1620 | enum ieee80211_band band); | 1616 | enum ieee80211_band band); |
1621 | 1617 | ||
1622 | /* channel management */ | 1618 | /* channel management */ |
1623 | enum nl80211_channel_type | 1619 | void ieee80211_ht_oper_to_chandef(struct ieee80211_channel *control_chan, |
1624 | ieee80211_ht_oper_to_channel_type(struct ieee80211_ht_operation *ht_oper); | 1620 | struct ieee80211_ht_operation *ht_oper, |
1621 | struct cfg80211_chan_def *chandef); | ||
1625 | 1622 | ||
1626 | int __must_check | 1623 | int __must_check |
1627 | ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata, | 1624 | ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata, |
1628 | struct ieee80211_channel *channel, | 1625 | const struct cfg80211_chan_def *chandef, |
1629 | enum nl80211_channel_type channel_type, | ||
1630 | enum ieee80211_chanctx_mode mode); | 1626 | enum ieee80211_chanctx_mode mode); |
1631 | void ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata); | 1627 | void ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata); |
1632 | 1628 | ||
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 80ce90b29d9d..5331662489f7 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -54,7 +54,7 @@ bool __ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata) | |||
54 | return false; | 54 | return false; |
55 | } | 55 | } |
56 | 56 | ||
57 | power = chanctx_conf->channel->max_power; | 57 | power = chanctx_conf->def.chan->max_power; |
58 | rcu_read_unlock(); | 58 | rcu_read_unlock(); |
59 | 59 | ||
60 | if (sdata->user_power_level != IEEE80211_UNSET_POWER_LEVEL) | 60 | if (sdata->user_power_level != IEEE80211_UNSET_POWER_LEVEL) |
@@ -415,8 +415,7 @@ static int ieee80211_add_virtual_monitor(struct ieee80211_local *local) | |||
415 | goto out_unlock; | 415 | goto out_unlock; |
416 | } | 416 | } |
417 | 417 | ||
418 | ret = ieee80211_vif_use_channel(sdata, local->monitor_channel, | 418 | ret = ieee80211_vif_use_channel(sdata, &local->monitor_chandef, |
419 | local->monitor_channel_type, | ||
420 | IEEE80211_CHANCTX_EXCLUSIVE); | 419 | IEEE80211_CHANCTX_EXCLUSIVE); |
421 | if (ret) { | 420 | if (ret) { |
422 | drv_remove_interface(local, sdata); | 421 | drv_remove_interface(local, sdata); |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index da2f41610125..f5e4c1f24bf2 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -115,7 +115,7 @@ static u32 ieee80211_hw_conf_chan(struct ieee80211_local *local) | |||
115 | channel_type = NL80211_CHAN_NO_HT; | 115 | channel_type = NL80211_CHAN_NO_HT; |
116 | } else if (local->tmp_channel) { | 116 | } else if (local->tmp_channel) { |
117 | chan = local->tmp_channel; | 117 | chan = local->tmp_channel; |
118 | channel_type = local->tmp_channel_type; | 118 | channel_type = NL80211_CHAN_NO_HT; |
119 | } else { | 119 | } else { |
120 | chan = local->_oper_channel; | 120 | chan = local->_oper_channel; |
121 | channel_type = local->_oper_channel_type; | 121 | channel_type = local->_oper_channel_type; |
@@ -798,10 +798,9 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
798 | local->_oper_channel = &sband->channels[0]; | 798 | local->_oper_channel = &sband->channels[0]; |
799 | local->hw.conf.channel_type = NL80211_CHAN_NO_HT; | 799 | local->hw.conf.channel_type = NL80211_CHAN_NO_HT; |
800 | } | 800 | } |
801 | if (!local->monitor_channel) { | 801 | cfg80211_chandef_create(&local->monitor_chandef, |
802 | local->monitor_channel = &sband->channels[0]; | 802 | &sband->channels[0], |
803 | local->monitor_channel_type = NL80211_CHAN_NO_HT; | 803 | NL80211_CHAN_NO_HT); |
804 | } | ||
805 | channels += sband->n_channels; | 804 | channels += sband->n_channels; |
806 | 805 | ||
807 | if (max_bitrates < sband->n_bitrates) | 806 | if (max_bitrates < sband->n_bitrates) |
@@ -884,10 +883,22 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
884 | if (supp_ht) | 883 | if (supp_ht) |
885 | local->scan_ies_len += 2 + sizeof(struct ieee80211_ht_cap); | 884 | local->scan_ies_len += 2 + sizeof(struct ieee80211_ht_cap); |
886 | 885 | ||
887 | if (supp_vht) | 886 | if (supp_vht) { |
888 | local->scan_ies_len += | 887 | local->scan_ies_len += |
889 | 2 + sizeof(struct ieee80211_vht_cap); | 888 | 2 + sizeof(struct ieee80211_vht_cap); |
890 | 889 | ||
890 | /* | ||
891 | * (for now at least), drivers wanting to use VHT must | ||
892 | * support channel contexts, as they contain all the | ||
893 | * necessary VHT information and the global hw config | ||
894 | * doesn't (yet) | ||
895 | */ | ||
896 | if (WARN_ON(!local->use_chanctx)) { | ||
897 | result = -EINVAL; | ||
898 | goto fail_wiphy_register; | ||
899 | } | ||
900 | } | ||
901 | |||
891 | if (!local->ops->hw_scan) { | 902 | if (!local->ops->hw_scan) { |
892 | /* For hw_scan, driver needs to set these up. */ | 903 | /* For hw_scan, driver needs to set these up. */ |
893 | local->hw.wiphy->max_scan_ssids = 4; | 904 | local->hw.wiphy->max_scan_ssids = 4; |
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index a350cab4b339..1bf03f9ff3ba 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c | |||
@@ -76,7 +76,7 @@ bool mesh_matches_local(struct ieee80211_sub_if_data *sdata, | |||
76 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | 76 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
77 | struct ieee80211_local *local = sdata->local; | 77 | struct ieee80211_local *local = sdata->local; |
78 | u32 basic_rates = 0; | 78 | u32 basic_rates = 0; |
79 | enum nl80211_channel_type sta_channel_type = NL80211_CHAN_NO_HT; | 79 | struct cfg80211_chan_def sta_chan_def; |
80 | 80 | ||
81 | /* | 81 | /* |
82 | * As support for each feature is added, check for matching | 82 | * As support for each feature is added, check for matching |
@@ -103,17 +103,11 @@ bool mesh_matches_local(struct ieee80211_sub_if_data *sdata, | |||
103 | if (sdata->vif.bss_conf.basic_rates != basic_rates) | 103 | if (sdata->vif.bss_conf.basic_rates != basic_rates) |
104 | goto mismatch; | 104 | goto mismatch; |
105 | 105 | ||
106 | if (ie->ht_operation) | 106 | ieee80211_ht_oper_to_chandef(sdata->vif.bss_conf.chandef.chan, |
107 | sta_channel_type = | 107 | ie->ht_operation, &sta_chan_def); |
108 | ieee80211_ht_oper_to_channel_type(ie->ht_operation); | 108 | |
109 | 109 | if (!cfg80211_chandef_compatible(&sdata->vif.bss_conf.chandef, | |
110 | /* Disallow HT40+/- mismatch */ | 110 | &sta_chan_def)) |
111 | if (ie->ht_operation && | ||
112 | (sdata->vif.bss_conf.channel_type == NL80211_CHAN_HT40MINUS || | ||
113 | sdata->vif.bss_conf.channel_type == NL80211_CHAN_HT40PLUS) && | ||
114 | (sta_channel_type == NL80211_CHAN_HT40MINUS || | ||
115 | sta_channel_type == NL80211_CHAN_HT40PLUS) && | ||
116 | sdata->vif.bss_conf.channel_type != sta_channel_type) | ||
117 | goto mismatch; | 111 | goto mismatch; |
118 | 112 | ||
119 | return true; | 113 | return true; |
@@ -129,7 +123,7 @@ mismatch: | |||
129 | bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie) | 123 | bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie) |
130 | { | 124 | { |
131 | return (ie->mesh_config->meshconf_cap & | 125 | return (ie->mesh_config->meshconf_cap & |
132 | MESHCONF_CAPAB_ACCEPT_PLINKS) != 0; | 126 | IEEE80211_MESHCONF_CAPAB_ACCEPT_PLINKS) != 0; |
133 | } | 127 | } |
134 | 128 | ||
135 | /** | 129 | /** |
@@ -269,11 +263,11 @@ mesh_add_meshconf_ie(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata) | |||
269 | neighbors = (neighbors > 15) ? 15 : neighbors; | 263 | neighbors = (neighbors > 15) ? 15 : neighbors; |
270 | *pos++ = neighbors << 1; | 264 | *pos++ = neighbors << 1; |
271 | /* Mesh capability */ | 265 | /* Mesh capability */ |
272 | *pos = MESHCONF_CAPAB_FORWARDING; | 266 | *pos = IEEE80211_MESHCONF_CAPAB_FORWARDING; |
273 | *pos |= ifmsh->accepting_plinks ? | 267 | *pos |= ifmsh->accepting_plinks ? |
274 | MESHCONF_CAPAB_ACCEPT_PLINKS : 0x00; | 268 | IEEE80211_MESHCONF_CAPAB_ACCEPT_PLINKS : 0x00; |
275 | *pos++ |= ifmsh->adjusting_tbtt ? | 269 | *pos++ |= ifmsh->adjusting_tbtt ? |
276 | MESHCONF_CAPAB_TBTT_ADJUSTING : 0x00; | 270 | IEEE80211_MESHCONF_CAPAB_TBTT_ADJUSTING : 0x00; |
277 | *pos++ = 0x00; | 271 | *pos++ = 0x00; |
278 | 272 | ||
279 | return 0; | 273 | return 0; |
@@ -368,7 +362,7 @@ int mesh_add_ds_params_ie(struct sk_buff *skb, | |||
368 | rcu_read_unlock(); | 362 | rcu_read_unlock(); |
369 | return -EINVAL; | 363 | return -EINVAL; |
370 | } | 364 | } |
371 | chan = chanctx_conf->channel; | 365 | chan = chanctx_conf->def.chan; |
372 | rcu_read_unlock(); | 366 | rcu_read_unlock(); |
373 | 367 | ||
374 | sband = local->hw.wiphy->bands[chan->band]; | 368 | sband = local->hw.wiphy->bands[chan->band]; |
@@ -392,7 +386,7 @@ int mesh_add_ht_cap_ie(struct sk_buff *skb, | |||
392 | 386 | ||
393 | sband = local->hw.wiphy->bands[band]; | 387 | sband = local->hw.wiphy->bands[band]; |
394 | if (!sband->ht_cap.ht_supported || | 388 | if (!sband->ht_cap.ht_supported || |
395 | sdata->vif.bss_conf.channel_type == NL80211_CHAN_NO_HT) | 389 | sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT) |
396 | return 0; | 390 | return 0; |
397 | 391 | ||
398 | if (skb_tailroom(skb) < 2 + sizeof(struct ieee80211_ht_cap)) | 392 | if (skb_tailroom(skb) < 2 + sizeof(struct ieee80211_ht_cap)) |
@@ -411,7 +405,7 @@ int mesh_add_ht_oper_ie(struct sk_buff *skb, | |||
411 | struct ieee80211_chanctx_conf *chanctx_conf; | 405 | struct ieee80211_chanctx_conf *chanctx_conf; |
412 | struct ieee80211_channel *channel; | 406 | struct ieee80211_channel *channel; |
413 | enum nl80211_channel_type channel_type = | 407 | enum nl80211_channel_type channel_type = |
414 | sdata->vif.bss_conf.channel_type; | 408 | cfg80211_get_chandef_type(&sdata->vif.bss_conf.chandef); |
415 | struct ieee80211_supported_band *sband; | 409 | struct ieee80211_supported_band *sband; |
416 | struct ieee80211_sta_ht_cap *ht_cap; | 410 | struct ieee80211_sta_ht_cap *ht_cap; |
417 | u8 *pos; | 411 | u8 *pos; |
@@ -422,7 +416,7 @@ int mesh_add_ht_oper_ie(struct sk_buff *skb, | |||
422 | rcu_read_unlock(); | 416 | rcu_read_unlock(); |
423 | return -EINVAL; | 417 | return -EINVAL; |
424 | } | 418 | } |
425 | channel = chanctx_conf->channel; | 419 | channel = chanctx_conf->def.chan; |
426 | rcu_read_unlock(); | 420 | rcu_read_unlock(); |
427 | 421 | ||
428 | sband = local->hw.wiphy->bands[channel->band]; | 422 | sband = local->hw.wiphy->bands[channel->band]; |
@@ -435,7 +429,7 @@ int mesh_add_ht_oper_ie(struct sk_buff *skb, | |||
435 | return -ENOMEM; | 429 | return -ENOMEM; |
436 | 430 | ||
437 | pos = skb_put(skb, 2 + sizeof(struct ieee80211_ht_operation)); | 431 | pos = skb_put(skb, 2 + sizeof(struct ieee80211_ht_operation)); |
438 | ieee80211_ie_build_ht_oper(pos, ht_cap, channel, channel_type, | 432 | ieee80211_ie_build_ht_oper(pos, ht_cap, &sdata->vif.bss_conf.chandef, |
439 | sdata->vif.bss_conf.ht_operation_mode); | 433 | sdata->vif.bss_conf.ht_operation_mode); |
440 | 434 | ||
441 | return 0; | 435 | return 0; |
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h index 9285f3f67e66..7c9215fb2ac8 100644 --- a/net/mac80211/mesh.h +++ b/net/mac80211/mesh.h | |||
@@ -19,20 +19,6 @@ | |||
19 | /* Data structures */ | 19 | /* Data structures */ |
20 | 20 | ||
21 | /** | 21 | /** |
22 | * enum mesh_config_capab_flags - mesh config IE capability flags | ||
23 | * | ||
24 | * @MESHCONF_CAPAB_ACCEPT_PLINKS: STA is willing to establish | ||
25 | * additional mesh peerings with other mesh STAs | ||
26 | * @MESHCONF_CAPAB_FORWARDING: the STA forwards MSDUs | ||
27 | * @MESHCONF_CAPAB_TBTT_ADJUSTING: TBTT adjustment procedure is ongoing | ||
28 | */ | ||
29 | enum mesh_config_capab_flags { | ||
30 | MESHCONF_CAPAB_ACCEPT_PLINKS = BIT(0), | ||
31 | MESHCONF_CAPAB_FORWARDING = BIT(3), | ||
32 | MESHCONF_CAPAB_TBTT_ADJUSTING = BIT(5), | ||
33 | }; | ||
34 | |||
35 | /** | ||
36 | * enum mesh_path_flags - mac80211 mesh path flags | 22 | * enum mesh_path_flags - mac80211 mesh path flags |
37 | * | 23 | * |
38 | * | 24 | * |
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index 234fe755968b..ca52dfdd5375 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c | |||
@@ -19,12 +19,6 @@ | |||
19 | #define mod_plink_timer(s, t) (mod_timer(&s->plink_timer, \ | 19 | #define mod_plink_timer(s, t) (mod_timer(&s->plink_timer, \ |
20 | jiffies + HZ * t / 1000)) | 20 | jiffies + HZ * t / 1000)) |
21 | 21 | ||
22 | #define dot11MeshMaxRetries(s) (s->u.mesh.mshcfg.dot11MeshMaxRetries) | ||
23 | #define dot11MeshRetryTimeout(s) (s->u.mesh.mshcfg.dot11MeshRetryTimeout) | ||
24 | #define dot11MeshConfirmTimeout(s) (s->u.mesh.mshcfg.dot11MeshConfirmTimeout) | ||
25 | #define dot11MeshHoldingTimeout(s) (s->u.mesh.mshcfg.dot11MeshHoldingTimeout) | ||
26 | #define dot11MeshMaxPeerLinks(s) (s->u.mesh.mshcfg.dot11MeshMaxPeerLinks) | ||
27 | |||
28 | /* We only need a valid sta if user configured a minimum rssi_threshold. */ | 22 | /* We only need a valid sta if user configured a minimum rssi_threshold. */ |
29 | #define rssi_threshold_check(sta, sdata) \ | 23 | #define rssi_threshold_check(sta, sdata) \ |
30 | (sdata->u.mesh.mshcfg.rssi_threshold == 0 ||\ | 24 | (sdata->u.mesh.mshcfg.rssi_threshold == 0 ||\ |
@@ -117,7 +111,7 @@ static u32 mesh_set_ht_prot_mode(struct ieee80211_sub_if_data *sdata) | |||
117 | u16 ht_opmode; | 111 | u16 ht_opmode; |
118 | bool non_ht_sta = false, ht20_sta = false; | 112 | bool non_ht_sta = false, ht20_sta = false; |
119 | 113 | ||
120 | if (sdata->vif.bss_conf.channel_type == NL80211_CHAN_NO_HT) | 114 | if (sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT) |
121 | return 0; | 115 | return 0; |
122 | 116 | ||
123 | rcu_read_lock(); | 117 | rcu_read_lock(); |
@@ -126,14 +120,14 @@ static u32 mesh_set_ht_prot_mode(struct ieee80211_sub_if_data *sdata) | |||
126 | sta->plink_state != NL80211_PLINK_ESTAB) | 120 | sta->plink_state != NL80211_PLINK_ESTAB) |
127 | continue; | 121 | continue; |
128 | 122 | ||
129 | switch (sta->ch_type) { | 123 | switch (sta->ch_width) { |
130 | case NL80211_CHAN_NO_HT: | 124 | case NL80211_CHAN_WIDTH_20_NOHT: |
131 | mpl_dbg(sdata, | 125 | mpl_dbg(sdata, |
132 | "mesh_plink %pM: nonHT sta (%pM) is present\n", | 126 | "mesh_plink %pM: nonHT sta (%pM) is present\n", |
133 | sdata->vif.addr, sta->sta.addr); | 127 | sdata->vif.addr, sta->sta.addr); |
134 | non_ht_sta = true; | 128 | non_ht_sta = true; |
135 | goto out; | 129 | goto out; |
136 | case NL80211_CHAN_HT20: | 130 | case NL80211_CHAN_WIDTH_20: |
137 | mpl_dbg(sdata, | 131 | mpl_dbg(sdata, |
138 | "mesh_plink %pM: HT20 sta (%pM) is present\n", | 132 | "mesh_plink %pM: HT20 sta (%pM) is present\n", |
139 | sdata->vif.addr, sta->sta.addr); | 133 | sdata->vif.addr, sta->sta.addr); |
@@ -148,7 +142,7 @@ out: | |||
148 | if (non_ht_sta) | 142 | if (non_ht_sta) |
149 | ht_opmode = IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED; | 143 | ht_opmode = IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED; |
150 | else if (ht20_sta && | 144 | else if (ht20_sta && |
151 | sdata->vif.bss_conf.channel_type > NL80211_CHAN_HT20) | 145 | sdata->vif.bss_conf.chandef.width > NL80211_CHAN_WIDTH_20) |
152 | ht_opmode = IEEE80211_HT_OP_MODE_PROTECTION_20MHZ; | 146 | ht_opmode = IEEE80211_HT_OP_MODE_PROTECTION_20MHZ; |
153 | else | 147 | else |
154 | ht_opmode = IEEE80211_HT_OP_MODE_PROTECTION_NONE; | 148 | ht_opmode = IEEE80211_HT_OP_MODE_PROTECTION_NONE; |
@@ -378,7 +372,7 @@ static struct sta_info *mesh_peer_init(struct ieee80211_sub_if_data *sdata, | |||
378 | 372 | ||
379 | sta->sta.supp_rates[band] = rates; | 373 | sta->sta.supp_rates[band] = rates; |
380 | if (elems->ht_cap_elem && | 374 | if (elems->ht_cap_elem && |
381 | sdata->vif.bss_conf.channel_type != NL80211_CHAN_NO_HT) | 375 | sdata->vif.bss_conf.chandef.width != NL80211_CHAN_WIDTH_20_NOHT) |
382 | ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband, | 376 | ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband, |
383 | elems->ht_cap_elem, | 377 | elems->ht_cap_elem, |
384 | &sta->sta.ht_cap); | 378 | &sta->sta.ht_cap); |
@@ -386,12 +380,15 @@ static struct sta_info *mesh_peer_init(struct ieee80211_sub_if_data *sdata, | |||
386 | memset(&sta->sta.ht_cap, 0, sizeof(sta->sta.ht_cap)); | 380 | memset(&sta->sta.ht_cap, 0, sizeof(sta->sta.ht_cap)); |
387 | 381 | ||
388 | if (elems->ht_operation) { | 382 | if (elems->ht_operation) { |
383 | struct cfg80211_chan_def chandef; | ||
384 | |||
389 | if (!(elems->ht_operation->ht_param & | 385 | if (!(elems->ht_operation->ht_param & |
390 | IEEE80211_HT_PARAM_CHAN_WIDTH_ANY)) | 386 | IEEE80211_HT_PARAM_CHAN_WIDTH_ANY)) |
391 | sta->sta.ht_cap.cap &= | 387 | sta->sta.ht_cap.cap &= |
392 | ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; | 388 | ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; |
393 | sta->ch_type = | 389 | ieee80211_ht_oper_to_chandef(sdata->vif.bss_conf.chandef.chan, |
394 | ieee80211_ht_oper_to_channel_type(elems->ht_operation); | 390 | elems->ht_operation, &chandef); |
391 | sta->ch_width = chandef.width; | ||
395 | } | 392 | } |
396 | 393 | ||
397 | rate_control_rate_init(sta); | 394 | rate_control_rate_init(sta); |
@@ -430,6 +427,7 @@ static void mesh_plink_timer(unsigned long data) | |||
430 | struct sta_info *sta; | 427 | struct sta_info *sta; |
431 | __le16 llid, plid, reason; | 428 | __le16 llid, plid, reason; |
432 | struct ieee80211_sub_if_data *sdata; | 429 | struct ieee80211_sub_if_data *sdata; |
430 | struct mesh_config *mshcfg; | ||
433 | 431 | ||
434 | /* | 432 | /* |
435 | * This STA is valid because sta_info_destroy() will | 433 | * This STA is valid because sta_info_destroy() will |
@@ -456,12 +454,13 @@ static void mesh_plink_timer(unsigned long data) | |||
456 | llid = sta->llid; | 454 | llid = sta->llid; |
457 | plid = sta->plid; | 455 | plid = sta->plid; |
458 | sdata = sta->sdata; | 456 | sdata = sta->sdata; |
457 | mshcfg = &sdata->u.mesh.mshcfg; | ||
459 | 458 | ||
460 | switch (sta->plink_state) { | 459 | switch (sta->plink_state) { |
461 | case NL80211_PLINK_OPN_RCVD: | 460 | case NL80211_PLINK_OPN_RCVD: |
462 | case NL80211_PLINK_OPN_SNT: | 461 | case NL80211_PLINK_OPN_SNT: |
463 | /* retry timer */ | 462 | /* retry timer */ |
464 | if (sta->plink_retries < dot11MeshMaxRetries(sdata)) { | 463 | if (sta->plink_retries < mshcfg->dot11MeshMaxRetries) { |
465 | u32 rand; | 464 | u32 rand; |
466 | mpl_dbg(sta->sdata, | 465 | mpl_dbg(sta->sdata, |
467 | "Mesh plink for %pM (retry, timeout): %d %d\n", | 466 | "Mesh plink for %pM (retry, timeout): %d %d\n", |
@@ -484,7 +483,7 @@ static void mesh_plink_timer(unsigned long data) | |||
484 | if (!reason) | 483 | if (!reason) |
485 | reason = cpu_to_le16(WLAN_REASON_MESH_CONFIRM_TIMEOUT); | 484 | reason = cpu_to_le16(WLAN_REASON_MESH_CONFIRM_TIMEOUT); |
486 | sta->plink_state = NL80211_PLINK_HOLDING; | 485 | sta->plink_state = NL80211_PLINK_HOLDING; |
487 | mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata)); | 486 | mod_plink_timer(sta, mshcfg->dot11MeshHoldingTimeout); |
488 | spin_unlock_bh(&sta->lock); | 487 | spin_unlock_bh(&sta->lock); |
489 | mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE, | 488 | mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE, |
490 | sta->sta.addr, llid, plid, reason); | 489 | sta->sta.addr, llid, plid, reason); |
@@ -543,7 +542,7 @@ int mesh_plink_open(struct sta_info *sta) | |||
543 | return -EBUSY; | 542 | return -EBUSY; |
544 | } | 543 | } |
545 | sta->plink_state = NL80211_PLINK_OPN_SNT; | 544 | sta->plink_state = NL80211_PLINK_OPN_SNT; |
546 | mesh_plink_timer_set(sta, dot11MeshRetryTimeout(sdata)); | 545 | mesh_plink_timer_set(sta, sdata->u.mesh.mshcfg.dot11MeshRetryTimeout); |
547 | spin_unlock_bh(&sta->lock); | 546 | spin_unlock_bh(&sta->lock); |
548 | mpl_dbg(sdata, | 547 | mpl_dbg(sdata, |
549 | "Mesh plink: starting establishment with %pM\n", | 548 | "Mesh plink: starting establishment with %pM\n", |
@@ -570,6 +569,7 @@ void mesh_plink_block(struct sta_info *sta) | |||
570 | void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt, | 569 | void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_mgmt *mgmt, |
571 | size_t len, struct ieee80211_rx_status *rx_status) | 570 | size_t len, struct ieee80211_rx_status *rx_status) |
572 | { | 571 | { |
572 | struct mesh_config *mshcfg = &sdata->u.mesh.mshcfg; | ||
573 | struct ieee802_11_elems elems; | 573 | struct ieee802_11_elems elems; |
574 | struct sta_info *sta; | 574 | struct sta_info *sta; |
575 | enum plink_event event; | 575 | enum plink_event event; |
@@ -777,7 +777,8 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m | |||
777 | sta->plid = plid; | 777 | sta->plid = plid; |
778 | get_random_bytes(&llid, 2); | 778 | get_random_bytes(&llid, 2); |
779 | sta->llid = llid; | 779 | sta->llid = llid; |
780 | mesh_plink_timer_set(sta, dot11MeshRetryTimeout(sdata)); | 780 | mesh_plink_timer_set(sta, |
781 | mshcfg->dot11MeshRetryTimeout); | ||
781 | spin_unlock_bh(&sta->lock); | 782 | spin_unlock_bh(&sta->lock); |
782 | mesh_plink_frame_tx(sdata, | 783 | mesh_plink_frame_tx(sdata, |
783 | WLAN_SP_MESH_PEERING_OPEN, | 784 | WLAN_SP_MESH_PEERING_OPEN, |
@@ -803,7 +804,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m | |||
803 | sta->reason = reason; | 804 | sta->reason = reason; |
804 | sta->plink_state = NL80211_PLINK_HOLDING; | 805 | sta->plink_state = NL80211_PLINK_HOLDING; |
805 | if (!mod_plink_timer(sta, | 806 | if (!mod_plink_timer(sta, |
806 | dot11MeshHoldingTimeout(sdata))) | 807 | mshcfg->dot11MeshHoldingTimeout)) |
807 | sta->ignore_plink_timer = true; | 808 | sta->ignore_plink_timer = true; |
808 | 809 | ||
809 | llid = sta->llid; | 810 | llid = sta->llid; |
@@ -825,7 +826,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m | |||
825 | case CNF_ACPT: | 826 | case CNF_ACPT: |
826 | sta->plink_state = NL80211_PLINK_CNF_RCVD; | 827 | sta->plink_state = NL80211_PLINK_CNF_RCVD; |
827 | if (!mod_plink_timer(sta, | 828 | if (!mod_plink_timer(sta, |
828 | dot11MeshConfirmTimeout(sdata))) | 829 | mshcfg->dot11MeshConfirmTimeout)) |
829 | sta->ignore_plink_timer = true; | 830 | sta->ignore_plink_timer = true; |
830 | 831 | ||
831 | spin_unlock_bh(&sta->lock); | 832 | spin_unlock_bh(&sta->lock); |
@@ -847,7 +848,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m | |||
847 | sta->reason = reason; | 848 | sta->reason = reason; |
848 | sta->plink_state = NL80211_PLINK_HOLDING; | 849 | sta->plink_state = NL80211_PLINK_HOLDING; |
849 | if (!mod_plink_timer(sta, | 850 | if (!mod_plink_timer(sta, |
850 | dot11MeshHoldingTimeout(sdata))) | 851 | mshcfg->dot11MeshHoldingTimeout)) |
851 | sta->ignore_plink_timer = true; | 852 | sta->ignore_plink_timer = true; |
852 | 853 | ||
853 | llid = sta->llid; | 854 | llid = sta->llid; |
@@ -888,7 +889,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m | |||
888 | sta->reason = reason; | 889 | sta->reason = reason; |
889 | sta->plink_state = NL80211_PLINK_HOLDING; | 890 | sta->plink_state = NL80211_PLINK_HOLDING; |
890 | if (!mod_plink_timer(sta, | 891 | if (!mod_plink_timer(sta, |
891 | dot11MeshHoldingTimeout(sdata))) | 892 | mshcfg->dot11MeshHoldingTimeout)) |
892 | sta->ignore_plink_timer = true; | 893 | sta->ignore_plink_timer = true; |
893 | 894 | ||
894 | llid = sta->llid; | 895 | llid = sta->llid; |
@@ -923,7 +924,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m | |||
923 | changed |= __mesh_plink_deactivate(sta); | 924 | changed |= __mesh_plink_deactivate(sta); |
924 | sta->plink_state = NL80211_PLINK_HOLDING; | 925 | sta->plink_state = NL80211_PLINK_HOLDING; |
925 | llid = sta->llid; | 926 | llid = sta->llid; |
926 | mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata)); | 927 | mod_plink_timer(sta, mshcfg->dot11MeshHoldingTimeout); |
927 | spin_unlock_bh(&sta->lock); | 928 | spin_unlock_bh(&sta->lock); |
928 | changed |= mesh_set_ht_prot_mode(sdata); | 929 | changed |= mesh_set_ht_prot_mode(sdata); |
929 | mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE, | 930 | mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE, |
diff --git a/net/mac80211/mesh_sync.c b/net/mac80211/mesh_sync.c index 9c6ea9cfe1b3..0f40086cce18 100644 --- a/net/mac80211/mesh_sync.c +++ b/net/mac80211/mesh_sync.c | |||
@@ -43,7 +43,7 @@ struct sync_method { | |||
43 | static bool mesh_peer_tbtt_adjusting(struct ieee802_11_elems *ie) | 43 | static bool mesh_peer_tbtt_adjusting(struct ieee802_11_elems *ie) |
44 | { | 44 | { |
45 | return (ie->mesh_config->meshconf_cap & | 45 | return (ie->mesh_config->meshconf_cap & |
46 | MESHCONF_CAPAB_TBTT_ADJUSTING) != 0; | 46 | IEEE80211_MESHCONF_CAPAB_TBTT_ADJUSTING) != 0; |
47 | } | 47 | } |
48 | 48 | ||
49 | void mesh_sync_adjust_tbtt(struct ieee80211_sub_if_data *sdata) | 49 | void mesh_sync_adjust_tbtt(struct ieee80211_sub_if_data *sdata) |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 61614461e089..d2a4f78b4b0f 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -191,17 +191,19 @@ static u32 ieee80211_config_ht_tx(struct ieee80211_sub_if_data *sdata, | |||
191 | rcu_read_unlock(); | 191 | rcu_read_unlock(); |
192 | return 0; | 192 | return 0; |
193 | } | 193 | } |
194 | chan = chanctx_conf->channel; | 194 | chan = chanctx_conf->def.chan; |
195 | rcu_read_unlock(); | 195 | rcu_read_unlock(); |
196 | sband = local->hw.wiphy->bands[chan->band]; | 196 | sband = local->hw.wiphy->bands[chan->band]; |
197 | 197 | ||
198 | switch (sdata->vif.bss_conf.channel_type) { | 198 | switch (sdata->vif.bss_conf.chandef.width) { |
199 | case NL80211_CHAN_HT40PLUS: | 199 | case NL80211_CHAN_WIDTH_40: |
200 | if (chan->flags & IEEE80211_CHAN_NO_HT40PLUS) | 200 | if (sdata->vif.bss_conf.chandef.chan->center_freq > |
201 | sdata->vif.bss_conf.chandef.center_freq1 && | ||
202 | chan->flags & IEEE80211_CHAN_NO_HT40PLUS) | ||
201 | disable_40 = true; | 203 | disable_40 = true; |
202 | break; | 204 | if (sdata->vif.bss_conf.chandef.chan->center_freq < |
203 | case NL80211_CHAN_HT40MINUS: | 205 | sdata->vif.bss_conf.chandef.center_freq1 && |
204 | if (chan->flags & IEEE80211_CHAN_NO_HT40MINUS) | 206 | chan->flags & IEEE80211_CHAN_NO_HT40MINUS) |
205 | disable_40 = true; | 207 | disable_40 = true; |
206 | break; | 208 | break; |
207 | default: | 209 | default: |
@@ -381,7 +383,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) | |||
381 | rcu_read_unlock(); | 383 | rcu_read_unlock(); |
382 | return; | 384 | return; |
383 | } | 385 | } |
384 | chan = chanctx_conf->channel; | 386 | chan = chanctx_conf->def.chan; |
385 | rcu_read_unlock(); | 387 | rcu_read_unlock(); |
386 | sband = local->hw.wiphy->bands[chan->band]; | 388 | sband = local->hw.wiphy->bands[chan->band]; |
387 | 389 | ||
@@ -541,7 +543,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) | |||
541 | offset = noffset; | 543 | offset = noffset; |
542 | } | 544 | } |
543 | 545 | ||
544 | if (!(ifmgd->flags & IEEE80211_STA_DISABLE_11N)) | 546 | if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HT)) |
545 | ieee80211_add_ht_ie(sdata, skb, assoc_data->ap_ht_param, | 547 | ieee80211_add_ht_ie(sdata, skb, assoc_data->ap_ht_param, |
546 | sband, chan, sdata->smps_mode); | 548 | sband, chan, sdata->smps_mode); |
547 | 549 | ||
@@ -1528,8 +1530,6 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1528 | changed |= BSS_CHANGED_BSSID | BSS_CHANGED_HT; | 1530 | changed |= BSS_CHANGED_BSSID | BSS_CHANGED_HT; |
1529 | ieee80211_bss_info_change_notify(sdata, changed); | 1531 | ieee80211_bss_info_change_notify(sdata, changed); |
1530 | 1532 | ||
1531 | ieee80211_vif_release_channel(sdata); | ||
1532 | |||
1533 | /* disassociated - set to defaults now */ | 1533 | /* disassociated - set to defaults now */ |
1534 | ieee80211_set_wmm_default(sdata, false); | 1534 | ieee80211_set_wmm_default(sdata, false); |
1535 | 1535 | ||
@@ -1539,6 +1539,9 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1539 | del_timer_sync(&sdata->u.mgd.chswitch_timer); | 1539 | del_timer_sync(&sdata->u.mgd.chswitch_timer); |
1540 | 1540 | ||
1541 | sdata->u.mgd.timers_running = 0; | 1541 | sdata->u.mgd.timers_running = 0; |
1542 | |||
1543 | ifmgd->flags = 0; | ||
1544 | ieee80211_vif_release_channel(sdata); | ||
1542 | } | 1545 | } |
1543 | 1546 | ||
1544 | void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata, | 1547 | void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata, |
@@ -1864,6 +1867,7 @@ static void ieee80211_destroy_auth_data(struct ieee80211_sub_if_data *sdata, | |||
1864 | 1867 | ||
1865 | memset(sdata->u.mgd.bssid, 0, ETH_ALEN); | 1868 | memset(sdata->u.mgd.bssid, 0, ETH_ALEN); |
1866 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID); | 1869 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID); |
1870 | sdata->u.mgd.flags = 0; | ||
1867 | ieee80211_vif_release_channel(sdata); | 1871 | ieee80211_vif_release_channel(sdata); |
1868 | } | 1872 | } |
1869 | 1873 | ||
@@ -2106,6 +2110,7 @@ static void ieee80211_destroy_assoc_data(struct ieee80211_sub_if_data *sdata, | |||
2106 | 2110 | ||
2107 | memset(sdata->u.mgd.bssid, 0, ETH_ALEN); | 2111 | memset(sdata->u.mgd.bssid, 0, ETH_ALEN); |
2108 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID); | 2112 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID); |
2113 | sdata->u.mgd.flags = 0; | ||
2109 | ieee80211_vif_release_channel(sdata); | 2114 | ieee80211_vif_release_channel(sdata); |
2110 | } | 2115 | } |
2111 | 2116 | ||
@@ -2170,7 +2175,7 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, | |||
2170 | 2175 | ||
2171 | sband = local->hw.wiphy->bands[ieee80211_get_sdata_band(sdata)]; | 2176 | sband = local->hw.wiphy->bands[ieee80211_get_sdata_band(sdata)]; |
2172 | 2177 | ||
2173 | if (elems.ht_cap_elem && !(ifmgd->flags & IEEE80211_STA_DISABLE_11N)) | 2178 | if (elems.ht_cap_elem && !(ifmgd->flags & IEEE80211_STA_DISABLE_HT)) |
2174 | ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband, | 2179 | ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband, |
2175 | elems.ht_cap_elem, &sta->sta.ht_cap); | 2180 | elems.ht_cap_elem, &sta->sta.ht_cap); |
2176 | 2181 | ||
@@ -2222,7 +2227,7 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, | |||
2222 | changed |= BSS_CHANGED_QOS; | 2227 | changed |= BSS_CHANGED_QOS; |
2223 | 2228 | ||
2224 | if (elems.ht_operation && elems.wmm_param && | 2229 | if (elems.ht_operation && elems.wmm_param && |
2225 | !(ifmgd->flags & IEEE80211_STA_DISABLE_11N)) | 2230 | !(ifmgd->flags & IEEE80211_STA_DISABLE_HT)) |
2226 | changed |= ieee80211_config_ht_tx(sdata, elems.ht_operation, | 2231 | changed |= ieee80211_config_ht_tx(sdata, elems.ht_operation, |
2227 | cbss->bssid, false); | 2232 | cbss->bssid, false); |
2228 | 2233 | ||
@@ -2473,11 +2478,11 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
2473 | return; | 2478 | return; |
2474 | } | 2479 | } |
2475 | 2480 | ||
2476 | if (rx_status->freq != chanctx_conf->channel->center_freq) { | 2481 | if (rx_status->freq != chanctx_conf->def.chan->center_freq) { |
2477 | rcu_read_unlock(); | 2482 | rcu_read_unlock(); |
2478 | return; | 2483 | return; |
2479 | } | 2484 | } |
2480 | chan = chanctx_conf->channel; | 2485 | chan = chanctx_conf->def.chan; |
2481 | rcu_read_unlock(); | 2486 | rcu_read_unlock(); |
2482 | 2487 | ||
2483 | if (ifmgd->assoc_data && !ifmgd->assoc_data->have_beacon && | 2488 | if (ifmgd->assoc_data && !ifmgd->assoc_data->have_beacon && |
@@ -2658,7 +2663,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
2658 | 2663 | ||
2659 | 2664 | ||
2660 | if (elems.ht_cap_elem && elems.ht_operation && elems.wmm_param && | 2665 | if (elems.ht_cap_elem && elems.ht_operation && elems.wmm_param && |
2661 | !(ifmgd->flags & IEEE80211_STA_DISABLE_11N)) | 2666 | !(ifmgd->flags & IEEE80211_STA_DISABLE_HT)) |
2662 | changed |= ieee80211_config_ht_tx(sdata, elems.ht_operation, | 2667 | changed |= ieee80211_config_ht_tx(sdata, elems.ht_operation, |
2663 | bssid, true); | 2668 | bssid, true); |
2664 | 2669 | ||
@@ -3188,6 +3193,7 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata, | |||
3188 | const u8 *ht_oper_ie; | 3193 | const u8 *ht_oper_ie; |
3189 | const struct ieee80211_ht_operation *ht_oper = NULL; | 3194 | const struct ieee80211_ht_operation *ht_oper = NULL; |
3190 | struct ieee80211_supported_band *sband; | 3195 | struct ieee80211_supported_band *sband; |
3196 | struct cfg80211_chan_def chandef; | ||
3191 | 3197 | ||
3192 | sband = local->hw.wiphy->bands[cbss->channel->band]; | 3198 | sband = local->hw.wiphy->bands[cbss->channel->band]; |
3193 | 3199 | ||
@@ -3219,12 +3225,10 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata, | |||
3219 | ht_cfreq, ht_oper->primary_chan, | 3225 | ht_cfreq, ht_oper->primary_chan, |
3220 | cbss->channel->band); | 3226 | cbss->channel->band); |
3221 | ht_oper = NULL; | 3227 | ht_oper = NULL; |
3222 | } else { | ||
3223 | channel_type = NL80211_CHAN_HT20; | ||
3224 | } | 3228 | } |
3225 | } | 3229 | } |
3226 | 3230 | ||
3227 | if (ht_oper && sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) { | 3231 | if (ht_oper) { |
3228 | /* | 3232 | /* |
3229 | * cfg80211 already verified that the channel itself can | 3233 | * cfg80211 already verified that the channel itself can |
3230 | * be used, but it didn't check that we can do the right | 3234 | * be used, but it didn't check that we can do the right |
@@ -3237,19 +3241,26 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata, | |||
3237 | 3241 | ||
3238 | channel_type = NL80211_CHAN_HT20; | 3242 | channel_type = NL80211_CHAN_HT20; |
3239 | 3243 | ||
3240 | switch (ht_oper->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { | 3244 | if (sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) { |
3241 | case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: | 3245 | switch (ht_oper->ht_param & |
3242 | if (cbss->channel->flags & IEEE80211_CHAN_NO_HT40PLUS) | 3246 | IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { |
3243 | ifmgd->flags |= IEEE80211_STA_DISABLE_40MHZ; | 3247 | case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: |
3244 | else | 3248 | if (cbss->channel->flags & |
3245 | channel_type = NL80211_CHAN_HT40PLUS; | 3249 | IEEE80211_CHAN_NO_HT40PLUS) |
3246 | break; | 3250 | ifmgd->flags |= |
3247 | case IEEE80211_HT_PARAM_CHA_SEC_BELOW: | 3251 | IEEE80211_STA_DISABLE_40MHZ; |
3248 | if (cbss->channel->flags & IEEE80211_CHAN_NO_HT40MINUS) | 3252 | else |
3249 | ifmgd->flags |= IEEE80211_STA_DISABLE_40MHZ; | 3253 | channel_type = NL80211_CHAN_HT40PLUS; |
3250 | else | 3254 | break; |
3251 | channel_type = NL80211_CHAN_HT40MINUS; | 3255 | case IEEE80211_HT_PARAM_CHA_SEC_BELOW: |
3252 | break; | 3256 | if (cbss->channel->flags & |
3257 | IEEE80211_CHAN_NO_HT40MINUS) | ||
3258 | ifmgd->flags |= | ||
3259 | IEEE80211_STA_DISABLE_40MHZ; | ||
3260 | else | ||
3261 | channel_type = NL80211_CHAN_HT40MINUS; | ||
3262 | break; | ||
3263 | } | ||
3253 | } | 3264 | } |
3254 | 3265 | ||
3255 | ht_cap_ie = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, | 3266 | ht_cap_ie = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, |
@@ -3262,13 +3273,15 @@ static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata, | |||
3262 | sdata->needed_rx_chains = min(chains, local->rx_chains); | 3273 | sdata->needed_rx_chains = min(chains, local->rx_chains); |
3263 | } else { | 3274 | } else { |
3264 | sdata->needed_rx_chains = 1; | 3275 | sdata->needed_rx_chains = 1; |
3276 | sdata->u.mgd.flags |= IEEE80211_STA_DISABLE_HT; | ||
3265 | } | 3277 | } |
3266 | 3278 | ||
3267 | /* will change later if needed */ | 3279 | /* will change later if needed */ |
3268 | sdata->smps_mode = IEEE80211_SMPS_OFF; | 3280 | sdata->smps_mode = IEEE80211_SMPS_OFF; |
3269 | 3281 | ||
3270 | ieee80211_vif_release_channel(sdata); | 3282 | ieee80211_vif_release_channel(sdata); |
3271 | return ieee80211_vif_use_channel(sdata, cbss->channel, channel_type, | 3283 | cfg80211_chandef_create(&chandef, cbss->channel, channel_type); |
3284 | return ieee80211_vif_use_channel(sdata, &chandef, | ||
3272 | IEEE80211_CHANCTX_SHARED); | 3285 | IEEE80211_CHANCTX_SHARED); |
3273 | } | 3286 | } |
3274 | 3287 | ||
@@ -3530,13 +3543,6 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
3530 | 3543 | ||
3531 | /* prepare assoc data */ | 3544 | /* prepare assoc data */ |
3532 | 3545 | ||
3533 | /* | ||
3534 | * keep only the 40 MHz disable bit set as it might have | ||
3535 | * been set during authentication already, all other bits | ||
3536 | * should be reset for a new connection | ||
3537 | */ | ||
3538 | ifmgd->flags &= IEEE80211_STA_DISABLE_40MHZ; | ||
3539 | |||
3540 | ifmgd->beacon_crc_valid = false; | 3546 | ifmgd->beacon_crc_valid = false; |
3541 | 3547 | ||
3542 | /* | 3548 | /* |
@@ -3550,7 +3556,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
3550 | if (req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_WEP40 || | 3556 | if (req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_WEP40 || |
3551 | req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_TKIP || | 3557 | req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_TKIP || |
3552 | req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_WEP104) { | 3558 | req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_WEP104) { |
3553 | ifmgd->flags |= IEEE80211_STA_DISABLE_11N; | 3559 | ifmgd->flags |= IEEE80211_STA_DISABLE_HT; |
3554 | ifmgd->flags |= IEEE80211_STA_DISABLE_VHT; | 3560 | ifmgd->flags |= IEEE80211_STA_DISABLE_VHT; |
3555 | netdev_info(sdata->dev, | 3561 | netdev_info(sdata->dev, |
3556 | "disabling HT/VHT due to WEP/TKIP use\n"); | 3562 | "disabling HT/VHT due to WEP/TKIP use\n"); |
@@ -3558,7 +3564,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
3558 | } | 3564 | } |
3559 | 3565 | ||
3560 | if (req->flags & ASSOC_REQ_DISABLE_HT) { | 3566 | if (req->flags & ASSOC_REQ_DISABLE_HT) { |
3561 | ifmgd->flags |= IEEE80211_STA_DISABLE_11N; | 3567 | ifmgd->flags |= IEEE80211_STA_DISABLE_HT; |
3562 | ifmgd->flags |= IEEE80211_STA_DISABLE_VHT; | 3568 | ifmgd->flags |= IEEE80211_STA_DISABLE_VHT; |
3563 | } | 3569 | } |
3564 | 3570 | ||
@@ -3566,7 +3572,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
3566 | sband = local->hw.wiphy->bands[req->bss->channel->band]; | 3572 | sband = local->hw.wiphy->bands[req->bss->channel->band]; |
3567 | if (!sband->ht_cap.ht_supported || | 3573 | if (!sband->ht_cap.ht_supported || |
3568 | local->hw.queues < IEEE80211_NUM_ACS || !bss->wmm_used) { | 3574 | local->hw.queues < IEEE80211_NUM_ACS || !bss->wmm_used) { |
3569 | ifmgd->flags |= IEEE80211_STA_DISABLE_11N; | 3575 | ifmgd->flags |= IEEE80211_STA_DISABLE_HT; |
3570 | if (!bss->wmm_used) | 3576 | if (!bss->wmm_used) |
3571 | netdev_info(sdata->dev, | 3577 | netdev_info(sdata->dev, |
3572 | "disabling HT as WMM/QoS is not supported by the AP\n"); | 3578 | "disabling HT as WMM/QoS is not supported by the AP\n"); |
@@ -3611,7 +3617,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
3611 | assoc_data->ap_ht_param = | 3617 | assoc_data->ap_ht_param = |
3612 | ((struct ieee80211_ht_operation *)(ht_ie + 2))->ht_param; | 3618 | ((struct ieee80211_ht_operation *)(ht_ie + 2))->ht_param; |
3613 | else | 3619 | else |
3614 | ifmgd->flags |= IEEE80211_STA_DISABLE_11N; | 3620 | ifmgd->flags |= IEEE80211_STA_DISABLE_HT; |
3615 | 3621 | ||
3616 | if (bss->wmm_used && bss->uapsd_supported && | 3622 | if (bss->wmm_used && bss->uapsd_supported && |
3617 | (sdata->local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD)) { | 3623 | (sdata->local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD)) { |
diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c index 7f8a36510813..5abddfe3e101 100644 --- a/net/mac80211/offchannel.c +++ b/net/mac80211/offchannel.c | |||
@@ -205,8 +205,8 @@ void ieee80211_handle_roc_started(struct ieee80211_roc_work *roc) | |||
205 | } | 205 | } |
206 | } else { | 206 | } else { |
207 | cfg80211_ready_on_channel(&roc->sdata->wdev, roc->cookie, | 207 | cfg80211_ready_on_channel(&roc->sdata->wdev, roc->cookie, |
208 | roc->chan, roc->chan_type, | 208 | roc->chan, roc->req_duration, |
209 | roc->req_duration, GFP_KERNEL); | 209 | GFP_KERNEL); |
210 | } | 210 | } |
211 | 211 | ||
212 | roc->notified = true; | 212 | roc->notified = true; |
@@ -284,7 +284,6 @@ void ieee80211_start_next_roc(struct ieee80211_local *local) | |||
284 | duration = 10; | 284 | duration = 10; |
285 | 285 | ||
286 | ret = drv_remain_on_channel(local, roc->sdata, roc->chan, | 286 | ret = drv_remain_on_channel(local, roc->sdata, roc->chan, |
287 | roc->chan_type, | ||
288 | duration); | 287 | duration); |
289 | 288 | ||
290 | roc->started = true; | 289 | roc->started = true; |
@@ -321,7 +320,7 @@ void ieee80211_roc_notify_destroy(struct ieee80211_roc_work *roc) | |||
321 | if (!roc->mgmt_tx_cookie) | 320 | if (!roc->mgmt_tx_cookie) |
322 | cfg80211_remain_on_channel_expired(&roc->sdata->wdev, | 321 | cfg80211_remain_on_channel_expired(&roc->sdata->wdev, |
323 | roc->cookie, roc->chan, | 322 | roc->cookie, roc->chan, |
324 | roc->chan_type, GFP_KERNEL); | 323 | GFP_KERNEL); |
325 | 324 | ||
326 | list_for_each_entry_safe(dep, tmp, &roc->dependents, list) | 325 | list_for_each_entry_safe(dep, tmp, &roc->dependents, list) |
327 | ieee80211_roc_notify_destroy(dep); | 326 | ieee80211_roc_notify_destroy(dep); |
@@ -359,7 +358,6 @@ void ieee80211_sw_roc_work(struct work_struct *work) | |||
359 | ieee80211_recalc_idle(local); | 358 | ieee80211_recalc_idle(local); |
360 | 359 | ||
361 | local->tmp_channel = roc->chan; | 360 | local->tmp_channel = roc->chan; |
362 | local->tmp_channel_type = roc->chan_type; | ||
363 | ieee80211_hw_config(local, 0); | 361 | ieee80211_hw_config(local, 0); |
364 | 362 | ||
365 | /* tell userspace or send frame */ | 363 | /* tell userspace or send frame */ |
diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c index 3313c117b322..dd88381c53b7 100644 --- a/net/mac80211/rate.c +++ b/net/mac80211/rate.c | |||
@@ -391,7 +391,7 @@ static void rate_idx_match_mask(struct ieee80211_tx_rate *rate, | |||
391 | return; | 391 | return; |
392 | 392 | ||
393 | /* if HT BSS, and we handle a data frame, also try HT rates */ | 393 | /* if HT BSS, and we handle a data frame, also try HT rates */ |
394 | if (txrc->bss_conf->channel_type == NL80211_CHAN_NO_HT) | 394 | if (txrc->bss_conf->chandef.width == NL80211_CHAN_WIDTH_20_NOHT) |
395 | return; | 395 | return; |
396 | 396 | ||
397 | fc = hdr->frame_control; | 397 | fc = hdr->frame_control; |
@@ -408,8 +408,7 @@ static void rate_idx_match_mask(struct ieee80211_tx_rate *rate, | |||
408 | 408 | ||
409 | alt_rate.flags |= IEEE80211_TX_RC_MCS; | 409 | alt_rate.flags |= IEEE80211_TX_RC_MCS; |
410 | 410 | ||
411 | if ((txrc->bss_conf->channel_type == NL80211_CHAN_HT40MINUS) || | 411 | if (txrc->bss_conf->chandef.width == NL80211_CHAN_WIDTH_40) |
412 | (txrc->bss_conf->channel_type == NL80211_CHAN_HT40PLUS)) | ||
413 | alt_rate.flags |= IEEE80211_TX_RC_40_MHZ_WIDTH; | 412 | alt_rate.flags |= IEEE80211_TX_RC_40_MHZ_WIDTH; |
414 | 413 | ||
415 | if (rate_idx_match_mcs_mask(&alt_rate, mcs_mask)) { | 414 | if (rate_idx_match_mcs_mask(&alt_rate, mcs_mask)) { |
diff --git a/net/mac80211/rate.h b/net/mac80211/rate.h index ec198ef6aa8a..301386dabf88 100644 --- a/net/mac80211/rate.h +++ b/net/mac80211/rate.h | |||
@@ -65,7 +65,7 @@ static inline void rate_control_rate_init(struct sta_info *sta) | |||
65 | return; | 65 | return; |
66 | } | 66 | } |
67 | 67 | ||
68 | sband = local->hw.wiphy->bands[chanctx_conf->channel->band]; | 68 | sband = local->hw.wiphy->bands[chanctx_conf->def.chan->band]; |
69 | rcu_read_unlock(); | 69 | rcu_read_unlock(); |
70 | 70 | ||
71 | ref->ops->rate_init(ref->priv, sband, ista, priv_sta); | 71 | ref->ops->rate_init(ref->priv, sband, ista, priv_sta); |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index ec15a4929f7a..825f33cf7bbc 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -62,13 +62,16 @@ static struct sk_buff *remove_monitor_info(struct ieee80211_local *local, | |||
62 | static inline int should_drop_frame(struct sk_buff *skb, int present_fcs_len) | 62 | static inline int should_drop_frame(struct sk_buff *skb, int present_fcs_len) |
63 | { | 63 | { |
64 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); | 64 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); |
65 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | 65 | struct ieee80211_hdr *hdr; |
66 | |||
67 | hdr = (void *)(skb->data + status->vendor_radiotap_len); | ||
66 | 68 | ||
67 | if (status->flag & (RX_FLAG_FAILED_FCS_CRC | | 69 | if (status->flag & (RX_FLAG_FAILED_FCS_CRC | |
68 | RX_FLAG_FAILED_PLCP_CRC | | 70 | RX_FLAG_FAILED_PLCP_CRC | |
69 | RX_FLAG_AMPDU_IS_ZEROLEN)) | 71 | RX_FLAG_AMPDU_IS_ZEROLEN)) |
70 | return 1; | 72 | return 1; |
71 | if (unlikely(skb->len < 16 + present_fcs_len)) | 73 | if (unlikely(skb->len < 16 + present_fcs_len + |
74 | status->vendor_radiotap_len)) | ||
72 | return 1; | 75 | return 1; |
73 | if (ieee80211_is_ctl(hdr->frame_control) && | 76 | if (ieee80211_is_ctl(hdr->frame_control) && |
74 | !ieee80211_is_pspoll(hdr->frame_control) && | 77 | !ieee80211_is_pspoll(hdr->frame_control) && |
@@ -190,7 +193,7 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, | |||
190 | pos++; | 193 | pos++; |
191 | 194 | ||
192 | /* IEEE80211_RADIOTAP_RATE */ | 195 | /* IEEE80211_RADIOTAP_RATE */ |
193 | if (!rate || status->flag & RX_FLAG_HT) { | 196 | if (!rate || status->flag & (RX_FLAG_HT | RX_FLAG_VHT)) { |
194 | /* | 197 | /* |
195 | * Without rate information don't add it. If we have, | 198 | * Without rate information don't add it. If we have, |
196 | * MCS information is a separate field in radiotap, | 199 | * MCS information is a separate field in radiotap, |
@@ -210,7 +213,7 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, | |||
210 | if (status->band == IEEE80211_BAND_5GHZ) | 213 | if (status->band == IEEE80211_BAND_5GHZ) |
211 | put_unaligned_le16(IEEE80211_CHAN_OFDM | IEEE80211_CHAN_5GHZ, | 214 | put_unaligned_le16(IEEE80211_CHAN_OFDM | IEEE80211_CHAN_5GHZ, |
212 | pos); | 215 | pos); |
213 | else if (status->flag & RX_FLAG_HT) | 216 | else if (status->flag & (RX_FLAG_HT | RX_FLAG_VHT)) |
214 | put_unaligned_le16(IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ, | 217 | put_unaligned_le16(IEEE80211_CHAN_DYN | IEEE80211_CHAN_2GHZ, |
215 | pos); | 218 | pos); |
216 | else if (rate && rate->flags & IEEE80211_RATE_ERP_G) | 219 | else if (rate && rate->flags & IEEE80211_RATE_ERP_G) |
@@ -341,8 +344,8 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb, | |||
341 | if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS) | 344 | if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS) |
342 | present_fcs_len = FCS_LEN; | 345 | present_fcs_len = FCS_LEN; |
343 | 346 | ||
344 | /* make sure hdr->frame_control is on the linear part */ | 347 | /* ensure hdr->frame_control and vendor radiotap data are in skb head */ |
345 | if (!pskb_may_pull(origskb, 2)) { | 348 | if (!pskb_may_pull(origskb, 2 + status->vendor_radiotap_len)) { |
346 | dev_kfree_skb(origskb); | 349 | dev_kfree_skb(origskb); |
347 | return NULL; | 350 | return NULL; |
348 | } | 351 | } |
@@ -1338,17 +1341,22 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) | |||
1338 | 1341 | ||
1339 | /* | 1342 | /* |
1340 | * Update last_rx only for IBSS packets which are for the current | 1343 | * Update last_rx only for IBSS packets which are for the current |
1341 | * BSSID to avoid keeping the current IBSS network alive in cases | 1344 | * BSSID and for station already AUTHORIZED to avoid keeping the |
1342 | * where other STAs start using different BSSID. | 1345 | * current IBSS network alive in cases where other STAs start |
1346 | * using different BSSID. This will also give the station another | ||
1347 | * chance to restart the authentication/authorization in case | ||
1348 | * something went wrong the first time. | ||
1343 | */ | 1349 | */ |
1344 | if (rx->sdata->vif.type == NL80211_IFTYPE_ADHOC) { | 1350 | if (rx->sdata->vif.type == NL80211_IFTYPE_ADHOC) { |
1345 | u8 *bssid = ieee80211_get_bssid(hdr, rx->skb->len, | 1351 | u8 *bssid = ieee80211_get_bssid(hdr, rx->skb->len, |
1346 | NL80211_IFTYPE_ADHOC); | 1352 | NL80211_IFTYPE_ADHOC); |
1347 | if (ether_addr_equal(bssid, rx->sdata->u.ibss.bssid)) { | 1353 | if (ether_addr_equal(bssid, rx->sdata->u.ibss.bssid) && |
1354 | test_sta_flag(sta, WLAN_STA_AUTHORIZED)) { | ||
1348 | sta->last_rx = jiffies; | 1355 | sta->last_rx = jiffies; |
1349 | if (ieee80211_is_data(hdr->frame_control)) { | 1356 | if (ieee80211_is_data(hdr->frame_control)) { |
1350 | sta->last_rx_rate_idx = status->rate_idx; | 1357 | sta->last_rx_rate_idx = status->rate_idx; |
1351 | sta->last_rx_rate_flag = status->flag; | 1358 | sta->last_rx_rate_flag = status->flag; |
1359 | sta->last_rx_rate_vht_nss = status->vht_nss; | ||
1352 | } | 1360 | } |
1353 | } | 1361 | } |
1354 | } else if (!is_multicast_ether_addr(hdr->addr1)) { | 1362 | } else if (!is_multicast_ether_addr(hdr->addr1)) { |
@@ -1360,6 +1368,7 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) | |||
1360 | if (ieee80211_is_data(hdr->frame_control)) { | 1368 | if (ieee80211_is_data(hdr->frame_control)) { |
1361 | sta->last_rx_rate_idx = status->rate_idx; | 1369 | sta->last_rx_rate_idx = status->rate_idx; |
1362 | sta->last_rx_rate_flag = status->flag; | 1370 | sta->last_rx_rate_flag = status->flag; |
1371 | sta->last_rx_rate_vht_nss = status->vht_nss; | ||
1363 | } | 1372 | } |
1364 | } | 1373 | } |
1365 | 1374 | ||
@@ -2703,7 +2712,8 @@ static void ieee80211_rx_handlers_result(struct ieee80211_rx_data *rx, | |||
2703 | status = IEEE80211_SKB_RXCB((rx->skb)); | 2712 | status = IEEE80211_SKB_RXCB((rx->skb)); |
2704 | 2713 | ||
2705 | sband = rx->local->hw.wiphy->bands[status->band]; | 2714 | sband = rx->local->hw.wiphy->bands[status->band]; |
2706 | if (!(status->flag & RX_FLAG_HT)) | 2715 | if (!(status->flag & RX_FLAG_HT) && |
2716 | !(status->flag & RX_FLAG_VHT)) | ||
2707 | rate = &sband->bitrates[status->rate_idx]; | 2717 | rate = &sband->bitrates[status->rate_idx]; |
2708 | 2718 | ||
2709 | ieee80211_rx_cooked_monitor(rx, rate); | 2719 | ieee80211_rx_cooked_monitor(rx, rate); |
@@ -2870,8 +2880,8 @@ static int prepare_for_handlers(struct ieee80211_rx_data *rx, | |||
2870 | status->rx_flags &= ~IEEE80211_RX_RA_MATCH; | 2880 | status->rx_flags &= ~IEEE80211_RX_RA_MATCH; |
2871 | } else if (!rx->sta) { | 2881 | } else if (!rx->sta) { |
2872 | int rate_idx; | 2882 | int rate_idx; |
2873 | if (status->flag & RX_FLAG_HT) | 2883 | if (status->flag & (RX_FLAG_HT | RX_FLAG_VHT)) |
2874 | rate_idx = 0; /* TODO: HT rates */ | 2884 | rate_idx = 0; /* TODO: HT/VHT rates */ |
2875 | else | 2885 | else |
2876 | rate_idx = status->rate_idx; | 2886 | rate_idx = status->rate_idx; |
2877 | ieee80211_ibss_rx_no_sta(sdata, bssid, hdr->addr2, | 2887 | ieee80211_ibss_rx_no_sta(sdata, bssid, hdr->addr2, |
@@ -3147,6 +3157,13 @@ void ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
3147 | status->rate_idx, | 3157 | status->rate_idx, |
3148 | status->rate_idx)) | 3158 | status->rate_idx)) |
3149 | goto drop; | 3159 | goto drop; |
3160 | } else if (status->flag & RX_FLAG_VHT) { | ||
3161 | if (WARN_ONCE(status->rate_idx > 9 || | ||
3162 | !status->vht_nss || | ||
3163 | status->vht_nss > 8, | ||
3164 | "Rate marked as a VHT rate but data is invalid: MCS: %d, NSS: %d\n", | ||
3165 | status->rate_idx, status->vht_nss)) | ||
3166 | goto drop; | ||
3150 | } else { | 3167 | } else { |
3151 | if (WARN_ON(status->rate_idx >= sband->n_bitrates)) | 3168 | if (WARN_ON(status->rate_idx >= sband->n_bitrates)) |
3152 | goto drop; | 3169 | goto drop; |
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 8e9bb168b73b..f3340279aba3 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c | |||
@@ -174,7 +174,6 @@ void ieee80211_scan_rx(struct ieee80211_local *local, struct sk_buff *skb) | |||
174 | u8 *elements; | 174 | u8 *elements; |
175 | struct ieee80211_channel *channel; | 175 | struct ieee80211_channel *channel; |
176 | size_t baselen; | 176 | size_t baselen; |
177 | int freq; | ||
178 | bool beacon; | 177 | bool beacon; |
179 | struct ieee802_11_elems elems; | 178 | struct ieee802_11_elems elems; |
180 | 179 | ||
@@ -209,13 +208,7 @@ void ieee80211_scan_rx(struct ieee80211_local *local, struct sk_buff *skb) | |||
209 | 208 | ||
210 | ieee802_11_parse_elems(elements, skb->len - baselen, &elems); | 209 | ieee802_11_parse_elems(elements, skb->len - baselen, &elems); |
211 | 210 | ||
212 | if (elems.ds_params && elems.ds_params_len == 1) | 211 | channel = ieee80211_get_channel(local->hw.wiphy, rx_status->freq); |
213 | freq = ieee80211_channel_to_frequency(elems.ds_params[0], | ||
214 | rx_status->band); | ||
215 | else | ||
216 | freq = rx_status->freq; | ||
217 | |||
218 | channel = ieee80211_get_channel(local->hw.wiphy, freq); | ||
219 | 212 | ||
220 | if (!channel || channel->flags & IEEE80211_CHAN_DISABLED) | 213 | if (!channel || channel->flags & IEEE80211_CHAN_DISABLED) |
221 | return; | 214 | return; |
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index e6e5cb586ac0..f3e502502fee 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -1092,7 +1092,7 @@ static void ieee80211_send_null_response(struct ieee80211_sub_if_data *sdata, | |||
1092 | return; | 1092 | return; |
1093 | } | 1093 | } |
1094 | 1094 | ||
1095 | ieee80211_xmit(sdata, skb, chanctx_conf->channel->band); | 1095 | ieee80211_xmit(sdata, skb, chanctx_conf->def.chan->band); |
1096 | rcu_read_unlock(); | 1096 | rcu_read_unlock(); |
1097 | } | 1097 | } |
1098 | 1098 | ||
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 776f3d0b4a47..6835cea4e402 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h | |||
@@ -227,6 +227,7 @@ struct sta_ampdu_mlme { | |||
227 | * "the" transmit rate | 227 | * "the" transmit rate |
228 | * @last_rx_rate_idx: rx status rate index of the last data packet | 228 | * @last_rx_rate_idx: rx status rate index of the last data packet |
229 | * @last_rx_rate_flag: rx status flag of the last data packet | 229 | * @last_rx_rate_flag: rx status flag of the last data packet |
230 | * @last_rx_rate_vht_nss: rx status nss of last data packet | ||
230 | * @lock: used for locking all fields that require locking, see comments | 231 | * @lock: used for locking all fields that require locking, see comments |
231 | * in the header file. | 232 | * in the header file. |
232 | * @drv_unblock_wk: used for driver PS unblocking | 233 | * @drv_unblock_wk: used for driver PS unblocking |
@@ -272,7 +273,7 @@ struct sta_ampdu_mlme { | |||
272 | * @t_offset: timing offset relative to this host | 273 | * @t_offset: timing offset relative to this host |
273 | * @t_offset_setpoint: reference timing offset of this sta to be used when | 274 | * @t_offset_setpoint: reference timing offset of this sta to be used when |
274 | * calculating clockdrift | 275 | * calculating clockdrift |
275 | * @ch_type: peer's channel type | 276 | * @ch_width: peer's channel width |
276 | * @debugfs: debug filesystem info | 277 | * @debugfs: debug filesystem info |
277 | * @dead: set to true when sta is unlinked | 278 | * @dead: set to true when sta is unlinked |
278 | * @uploaded: set to true when sta is uploaded to the driver | 279 | * @uploaded: set to true when sta is uploaded to the driver |
@@ -343,7 +344,8 @@ struct sta_info { | |||
343 | unsigned long tx_fragments; | 344 | unsigned long tx_fragments; |
344 | struct ieee80211_tx_rate last_tx_rate; | 345 | struct ieee80211_tx_rate last_tx_rate; |
345 | int last_rx_rate_idx; | 346 | int last_rx_rate_idx; |
346 | int last_rx_rate_flag; | 347 | u32 last_rx_rate_flag; |
348 | u8 last_rx_rate_vht_nss; | ||
347 | u16 tid_seq[IEEE80211_QOS_CTL_TID_MASK + 1]; | 349 | u16 tid_seq[IEEE80211_QOS_CTL_TID_MASK + 1]; |
348 | 350 | ||
349 | /* | 351 | /* |
@@ -368,7 +370,7 @@ struct sta_info { | |||
368 | struct timer_list plink_timer; | 370 | struct timer_list plink_timer; |
369 | s64 t_offset; | 371 | s64 t_offset; |
370 | s64 t_offset_setpoint; | 372 | s64 t_offset_setpoint; |
371 | enum nl80211_channel_type ch_type; | 373 | enum nl80211_chan_width ch_width; |
372 | #endif | 374 | #endif |
373 | 375 | ||
374 | #ifdef CONFIG_MAC80211_DEBUGFS | 376 | #ifdef CONFIG_MAC80211_DEBUGFS |
diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h index e9579b7a2cd0..a8270b441a6f 100644 --- a/net/mac80211/trace.h +++ b/net/mac80211/trace.h | |||
@@ -28,16 +28,21 @@ | |||
28 | #define VIF_PR_FMT " vif:%s(%d%s)" | 28 | #define VIF_PR_FMT " vif:%s(%d%s)" |
29 | #define VIF_PR_ARG __get_str(vif_name), __entry->vif_type, __entry->p2p ? "/p2p" : "" | 29 | #define VIF_PR_ARG __get_str(vif_name), __entry->vif_type, __entry->p2p ? "/p2p" : "" |
30 | 30 | ||
31 | #define CHANCTX_ENTRY __field(int, freq) \ | 31 | #define CHANCTX_ENTRY __field(u32, control_freq) \ |
32 | __field(int, chantype) \ | 32 | __field(u32, chan_width) \ |
33 | __field(u32, center_freq1) \ | ||
34 | __field(u32, center_freq2) \ | ||
33 | __field(u8, rx_chains_static) \ | 35 | __field(u8, rx_chains_static) \ |
34 | __field(u8, rx_chains_dynamic) | 36 | __field(u8, rx_chains_dynamic) |
35 | #define CHANCTX_ASSIGN __entry->freq = ctx->conf.channel->center_freq; \ | 37 | #define CHANCTX_ASSIGN __entry->control_freq = ctx->conf.def.chan->center_freq;\ |
36 | __entry->chantype = ctx->conf.channel_type; \ | 38 | __entry->chan_width = ctx->conf.def.width; \ |
39 | __entry->center_freq1 = ctx->conf.def.center_freq1; \ | ||
40 | __entry->center_freq2 = ctx->conf.def.center_freq2; \ | ||
37 | __entry->rx_chains_static = ctx->conf.rx_chains_static; \ | 41 | __entry->rx_chains_static = ctx->conf.rx_chains_static; \ |
38 | __entry->rx_chains_dynamic = ctx->conf.rx_chains_dynamic | 42 | __entry->rx_chains_dynamic = ctx->conf.rx_chains_dynamic |
39 | #define CHANCTX_PR_FMT " freq:%d MHz chantype:%d chains:%d/%d" | 43 | #define CHANCTX_PR_FMT " control:%d MHz width:%d center: %d/%d MHz chains:%d/%d" |
40 | #define CHANCTX_PR_ARG __entry->freq, __entry->chantype, \ | 44 | #define CHANCTX_PR_ARG __entry->control_freq, __entry->chan_width, \ |
45 | __entry->center_freq1, __entry->center_freq2, \ | ||
41 | __entry->rx_chains_static, __entry->rx_chains_dynamic | 46 | __entry->rx_chains_static, __entry->rx_chains_dynamic |
42 | 47 | ||
43 | 48 | ||
@@ -334,7 +339,8 @@ TRACE_EVENT(drv_bss_info_changed, | |||
334 | __field(u16, ht_operation_mode) | 339 | __field(u16, ht_operation_mode) |
335 | __field(s32, cqm_rssi_thold); | 340 | __field(s32, cqm_rssi_thold); |
336 | __field(s32, cqm_rssi_hyst); | 341 | __field(s32, cqm_rssi_hyst); |
337 | __field(u32, channel_type); | 342 | __field(u32, channel_width); |
343 | __field(u32, channel_cfreq1); | ||
338 | __dynamic_array(u32, arp_addr_list, info->arp_addr_cnt); | 344 | __dynamic_array(u32, arp_addr_list, info->arp_addr_cnt); |
339 | __field(bool, arp_filter_enabled); | 345 | __field(bool, arp_filter_enabled); |
340 | __field(bool, qos); | 346 | __field(bool, qos); |
@@ -370,7 +376,8 @@ TRACE_EVENT(drv_bss_info_changed, | |||
370 | __entry->ht_operation_mode = info->ht_operation_mode; | 376 | __entry->ht_operation_mode = info->ht_operation_mode; |
371 | __entry->cqm_rssi_thold = info->cqm_rssi_thold; | 377 | __entry->cqm_rssi_thold = info->cqm_rssi_thold; |
372 | __entry->cqm_rssi_hyst = info->cqm_rssi_hyst; | 378 | __entry->cqm_rssi_hyst = info->cqm_rssi_hyst; |
373 | __entry->channel_type = info->channel_type; | 379 | __entry->channel_width = info->chandef.width; |
380 | __entry->channel_cfreq1 = info->chandef.center_freq1; | ||
374 | memcpy(__get_dynamic_array(arp_addr_list), info->arp_addr_list, | 381 | memcpy(__get_dynamic_array(arp_addr_list), info->arp_addr_list, |
375 | sizeof(u32) * info->arp_addr_cnt); | 382 | sizeof(u32) * info->arp_addr_cnt); |
376 | __entry->arp_filter_enabled = info->arp_filter_enabled; | 383 | __entry->arp_filter_enabled = info->arp_filter_enabled; |
@@ -1022,15 +1029,14 @@ TRACE_EVENT(drv_remain_on_channel, | |||
1022 | TP_PROTO(struct ieee80211_local *local, | 1029 | TP_PROTO(struct ieee80211_local *local, |
1023 | struct ieee80211_sub_if_data *sdata, | 1030 | struct ieee80211_sub_if_data *sdata, |
1024 | struct ieee80211_channel *chan, | 1031 | struct ieee80211_channel *chan, |
1025 | enum nl80211_channel_type chantype, unsigned int duration), | 1032 | unsigned int duration), |
1026 | 1033 | ||
1027 | TP_ARGS(local, sdata, chan, chantype, duration), | 1034 | TP_ARGS(local, sdata, chan, duration), |
1028 | 1035 | ||
1029 | TP_STRUCT__entry( | 1036 | TP_STRUCT__entry( |
1030 | LOCAL_ENTRY | 1037 | LOCAL_ENTRY |
1031 | VIF_ENTRY | 1038 | VIF_ENTRY |
1032 | __field(int, center_freq) | 1039 | __field(int, center_freq) |
1033 | __field(int, channel_type) | ||
1034 | __field(unsigned int, duration) | 1040 | __field(unsigned int, duration) |
1035 | ), | 1041 | ), |
1036 | 1042 | ||
@@ -1038,7 +1044,6 @@ TRACE_EVENT(drv_remain_on_channel, | |||
1038 | LOCAL_ASSIGN; | 1044 | LOCAL_ASSIGN; |
1039 | VIF_ASSIGN; | 1045 | VIF_ASSIGN; |
1040 | __entry->center_freq = chan->center_freq; | 1046 | __entry->center_freq = chan->center_freq; |
1041 | __entry->channel_type = chantype; | ||
1042 | __entry->duration = duration; | 1047 | __entry->duration = duration; |
1043 | ), | 1048 | ), |
1044 | 1049 | ||
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 04076250264b..d287a4f2c01b 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -1676,7 +1676,7 @@ netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb, | |||
1676 | if (!chanctx_conf) | 1676 | if (!chanctx_conf) |
1677 | goto fail_rcu; | 1677 | goto fail_rcu; |
1678 | 1678 | ||
1679 | chan = chanctx_conf->channel; | 1679 | chan = chanctx_conf->def.chan; |
1680 | 1680 | ||
1681 | /* | 1681 | /* |
1682 | * Frame injection is not allowed if beaconing is not allowed | 1682 | * Frame injection is not allowed if beaconing is not allowed |
@@ -1779,7 +1779,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1779 | chanctx_conf = rcu_dereference(ap_sdata->vif.chanctx_conf); | 1779 | chanctx_conf = rcu_dereference(ap_sdata->vif.chanctx_conf); |
1780 | if (!chanctx_conf) | 1780 | if (!chanctx_conf) |
1781 | goto fail_rcu; | 1781 | goto fail_rcu; |
1782 | band = chanctx_conf->channel->band; | 1782 | band = chanctx_conf->def.chan->band; |
1783 | if (sta) | 1783 | if (sta) |
1784 | break; | 1784 | break; |
1785 | /* fall through */ | 1785 | /* fall through */ |
@@ -1794,7 +1794,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1794 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); | 1794 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); |
1795 | if (!chanctx_conf) | 1795 | if (!chanctx_conf) |
1796 | goto fail_rcu; | 1796 | goto fail_rcu; |
1797 | band = chanctx_conf->channel->band; | 1797 | band = chanctx_conf->def.chan->band; |
1798 | break; | 1798 | break; |
1799 | case NL80211_IFTYPE_WDS: | 1799 | case NL80211_IFTYPE_WDS: |
1800 | fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS); | 1800 | fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS); |
@@ -1871,7 +1871,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1871 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); | 1871 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); |
1872 | if (!chanctx_conf) | 1872 | if (!chanctx_conf) |
1873 | goto fail_rcu; | 1873 | goto fail_rcu; |
1874 | band = chanctx_conf->channel->band; | 1874 | band = chanctx_conf->def.chan->band; |
1875 | break; | 1875 | break; |
1876 | #endif | 1876 | #endif |
1877 | case NL80211_IFTYPE_STATION: | 1877 | case NL80211_IFTYPE_STATION: |
@@ -1930,7 +1930,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1930 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); | 1930 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); |
1931 | if (!chanctx_conf) | 1931 | if (!chanctx_conf) |
1932 | goto fail_rcu; | 1932 | goto fail_rcu; |
1933 | band = chanctx_conf->channel->band; | 1933 | band = chanctx_conf->def.chan->band; |
1934 | break; | 1934 | break; |
1935 | case NL80211_IFTYPE_ADHOC: | 1935 | case NL80211_IFTYPE_ADHOC: |
1936 | /* DA SA BSSID */ | 1936 | /* DA SA BSSID */ |
@@ -1941,7 +1941,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1941 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); | 1941 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); |
1942 | if (!chanctx_conf) | 1942 | if (!chanctx_conf) |
1943 | goto fail_rcu; | 1943 | goto fail_rcu; |
1944 | band = chanctx_conf->channel->band; | 1944 | band = chanctx_conf->def.chan->band; |
1945 | break; | 1945 | break; |
1946 | default: | 1946 | default: |
1947 | goto fail_rcu; | 1947 | goto fail_rcu; |
@@ -2194,7 +2194,7 @@ static bool ieee80211_tx_pending_skb(struct ieee80211_local *local, | |||
2194 | return true; | 2194 | return true; |
2195 | } | 2195 | } |
2196 | result = ieee80211_tx(sdata, skb, true, | 2196 | result = ieee80211_tx(sdata, skb, true, |
2197 | chanctx_conf->channel->band); | 2197 | chanctx_conf->def.chan->band); |
2198 | } else { | 2198 | } else { |
2199 | struct sk_buff_head skbs; | 2199 | struct sk_buff_head skbs; |
2200 | 2200 | ||
@@ -2458,7 +2458,7 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, | |||
2458 | *pos++ = WLAN_EID_SSID; | 2458 | *pos++ = WLAN_EID_SSID; |
2459 | *pos++ = 0x0; | 2459 | *pos++ = 0x0; |
2460 | 2460 | ||
2461 | band = chanctx_conf->channel->band; | 2461 | band = chanctx_conf->def.chan->band; |
2462 | 2462 | ||
2463 | if (ieee80211_add_srates_ie(sdata, skb, true, band) || | 2463 | if (ieee80211_add_srates_ie(sdata, skb, true, band) || |
2464 | mesh_add_ds_params_ie(skb, sdata) || | 2464 | mesh_add_ds_params_ie(skb, sdata) || |
@@ -2477,7 +2477,7 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, | |||
2477 | goto out; | 2477 | goto out; |
2478 | } | 2478 | } |
2479 | 2479 | ||
2480 | band = chanctx_conf->channel->band; | 2480 | band = chanctx_conf->def.chan->band; |
2481 | 2481 | ||
2482 | info = IEEE80211_SKB_CB(skb); | 2482 | info = IEEE80211_SKB_CB(skb); |
2483 | 2483 | ||
@@ -2757,7 +2757,7 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw, | |||
2757 | info = IEEE80211_SKB_CB(skb); | 2757 | info = IEEE80211_SKB_CB(skb); |
2758 | 2758 | ||
2759 | tx.flags |= IEEE80211_TX_PS_BUFFERED; | 2759 | tx.flags |= IEEE80211_TX_PS_BUFFERED; |
2760 | info->band = chanctx_conf->channel->band; | 2760 | info->band = chanctx_conf->def.chan->band; |
2761 | 2761 | ||
2762 | if (invoke_tx_handlers(&tx)) | 2762 | if (invoke_tx_handlers(&tx)) |
2763 | skb = NULL; | 2763 | skb = NULL; |
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 9b99916f384f..08132ff98155 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -898,7 +898,7 @@ void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata, | |||
898 | rcu_read_lock(); | 898 | rcu_read_lock(); |
899 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); | 899 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); |
900 | use_11b = (chanctx_conf && | 900 | use_11b = (chanctx_conf && |
901 | chanctx_conf->channel->band == IEEE80211_BAND_2GHZ) && | 901 | chanctx_conf->def.chan->band == IEEE80211_BAND_2GHZ) && |
902 | !(sdata->flags & IEEE80211_SDATA_OPERATING_GMODE); | 902 | !(sdata->flags & IEEE80211_SDATA_OPERATING_GMODE); |
903 | rcu_read_unlock(); | 903 | rcu_read_unlock(); |
904 | 904 | ||
@@ -991,7 +991,7 @@ void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata, | |||
991 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); | 991 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); |
992 | 992 | ||
993 | if (chanctx_conf && | 993 | if (chanctx_conf && |
994 | chanctx_conf->channel->band == IEEE80211_BAND_2GHZ && | 994 | chanctx_conf->def.chan->band == IEEE80211_BAND_2GHZ && |
995 | have_higher_than_11mbit) | 995 | have_higher_than_11mbit) |
996 | sdata->flags |= IEEE80211_SDATA_OPERATING_GMODE; | 996 | sdata->flags |= IEEE80211_SDATA_OPERATING_GMODE; |
997 | else | 997 | else |
@@ -1873,8 +1873,7 @@ u8 *ieee80211_ie_build_vht_cap(u8 *pos, struct ieee80211_sta_vht_cap *vht_cap, | |||
1873 | } | 1873 | } |
1874 | 1874 | ||
1875 | u8 *ieee80211_ie_build_ht_oper(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap, | 1875 | u8 *ieee80211_ie_build_ht_oper(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap, |
1876 | struct ieee80211_channel *channel, | 1876 | const struct cfg80211_chan_def *chandef, |
1877 | enum nl80211_channel_type channel_type, | ||
1878 | u16 prot_mode) | 1877 | u16 prot_mode) |
1879 | { | 1878 | { |
1880 | struct ieee80211_ht_operation *ht_oper; | 1879 | struct ieee80211_ht_operation *ht_oper; |
@@ -1882,23 +1881,25 @@ u8 *ieee80211_ie_build_ht_oper(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap, | |||
1882 | *pos++ = WLAN_EID_HT_OPERATION; | 1881 | *pos++ = WLAN_EID_HT_OPERATION; |
1883 | *pos++ = sizeof(struct ieee80211_ht_operation); | 1882 | *pos++ = sizeof(struct ieee80211_ht_operation); |
1884 | ht_oper = (struct ieee80211_ht_operation *)pos; | 1883 | ht_oper = (struct ieee80211_ht_operation *)pos; |
1885 | ht_oper->primary_chan = | 1884 | ht_oper->primary_chan = ieee80211_frequency_to_channel( |
1886 | ieee80211_frequency_to_channel(channel->center_freq); | 1885 | chandef->chan->center_freq); |
1887 | switch (channel_type) { | 1886 | switch (chandef->width) { |
1888 | case NL80211_CHAN_HT40MINUS: | 1887 | case NL80211_CHAN_WIDTH_160: |
1889 | ht_oper->ht_param = IEEE80211_HT_PARAM_CHA_SEC_BELOW; | 1888 | case NL80211_CHAN_WIDTH_80P80: |
1890 | break; | 1889 | case NL80211_CHAN_WIDTH_80: |
1891 | case NL80211_CHAN_HT40PLUS: | 1890 | case NL80211_CHAN_WIDTH_40: |
1892 | ht_oper->ht_param = IEEE80211_HT_PARAM_CHA_SEC_ABOVE; | 1891 | if (chandef->center_freq1 > chandef->chan->center_freq) |
1892 | ht_oper->ht_param = IEEE80211_HT_PARAM_CHA_SEC_ABOVE; | ||
1893 | else | ||
1894 | ht_oper->ht_param = IEEE80211_HT_PARAM_CHA_SEC_BELOW; | ||
1893 | break; | 1895 | break; |
1894 | case NL80211_CHAN_HT20: | ||
1895 | default: | 1896 | default: |
1896 | ht_oper->ht_param = IEEE80211_HT_PARAM_CHA_SEC_NONE; | 1897 | ht_oper->ht_param = IEEE80211_HT_PARAM_CHA_SEC_NONE; |
1897 | break; | 1898 | break; |
1898 | } | 1899 | } |
1899 | if (ht_cap->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40 && | 1900 | if (ht_cap->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40 && |
1900 | channel_type != NL80211_CHAN_NO_HT && | 1901 | chandef->width != NL80211_CHAN_WIDTH_20_NOHT && |
1901 | channel_type != NL80211_CHAN_HT20) | 1902 | chandef->width != NL80211_CHAN_WIDTH_20) |
1902 | ht_oper->ht_param |= IEEE80211_HT_PARAM_CHAN_WIDTH_ANY; | 1903 | ht_oper->ht_param |= IEEE80211_HT_PARAM_CHAN_WIDTH_ANY; |
1903 | 1904 | ||
1904 | ht_oper->operation_mode = cpu_to_le16(prot_mode); | 1905 | ht_oper->operation_mode = cpu_to_le16(prot_mode); |
@@ -1912,13 +1913,17 @@ u8 *ieee80211_ie_build_ht_oper(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap, | |||
1912 | return pos + sizeof(struct ieee80211_ht_operation); | 1913 | return pos + sizeof(struct ieee80211_ht_operation); |
1913 | } | 1914 | } |
1914 | 1915 | ||
1915 | enum nl80211_channel_type | 1916 | void ieee80211_ht_oper_to_chandef(struct ieee80211_channel *control_chan, |
1916 | ieee80211_ht_oper_to_channel_type(struct ieee80211_ht_operation *ht_oper) | 1917 | struct ieee80211_ht_operation *ht_oper, |
1918 | struct cfg80211_chan_def *chandef) | ||
1917 | { | 1919 | { |
1918 | enum nl80211_channel_type channel_type; | 1920 | enum nl80211_channel_type channel_type; |
1919 | 1921 | ||
1920 | if (!ht_oper) | 1922 | if (!ht_oper) { |
1921 | return NL80211_CHAN_NO_HT; | 1923 | cfg80211_chandef_create(chandef, control_chan, |
1924 | NL80211_CHAN_NO_HT); | ||
1925 | return; | ||
1926 | } | ||
1922 | 1927 | ||
1923 | switch (ht_oper->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { | 1928 | switch (ht_oper->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { |
1924 | case IEEE80211_HT_PARAM_CHA_SEC_NONE: | 1929 | case IEEE80211_HT_PARAM_CHA_SEC_NONE: |
@@ -1934,7 +1939,7 @@ ieee80211_ht_oper_to_channel_type(struct ieee80211_ht_operation *ht_oper) | |||
1934 | channel_type = NL80211_CHAN_NO_HT; | 1939 | channel_type = NL80211_CHAN_NO_HT; |
1935 | } | 1940 | } |
1936 | 1941 | ||
1937 | return channel_type; | 1942 | cfg80211_chandef_create(chandef, control_chan, channel_type); |
1938 | } | 1943 | } |
1939 | 1944 | ||
1940 | int ieee80211_add_srates_ie(struct ieee80211_sub_if_data *sdata, | 1945 | int ieee80211_add_srates_ie(struct ieee80211_sub_if_data *sdata, |
@@ -2066,6 +2071,20 @@ u64 ieee80211_calculate_rx_timestamp(struct ieee80211_local *local, | |||
2066 | ri.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; | 2071 | ri.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; |
2067 | if (status->flag & RX_FLAG_SHORT_GI) | 2072 | if (status->flag & RX_FLAG_SHORT_GI) |
2068 | ri.flags |= RATE_INFO_FLAGS_SHORT_GI; | 2073 | ri.flags |= RATE_INFO_FLAGS_SHORT_GI; |
2074 | } else if (status->flag & RX_FLAG_VHT) { | ||
2075 | ri.flags |= RATE_INFO_FLAGS_VHT_MCS; | ||
2076 | ri.mcs = status->rate_idx; | ||
2077 | ri.nss = status->vht_nss; | ||
2078 | if (status->flag & RX_FLAG_40MHZ) | ||
2079 | ri.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; | ||
2080 | if (status->flag & RX_FLAG_80MHZ) | ||
2081 | ri.flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH; | ||
2082 | if (status->flag & RX_FLAG_80P80MHZ) | ||
2083 | ri.flags |= RATE_INFO_FLAGS_80P80_MHZ_WIDTH; | ||
2084 | if (status->flag & RX_FLAG_160MHZ) | ||
2085 | ri.flags |= RATE_INFO_FLAGS_160_MHZ_WIDTH; | ||
2086 | if (status->flag & RX_FLAG_SHORT_GI) | ||
2087 | ri.flags |= RATE_INFO_FLAGS_SHORT_GI; | ||
2069 | } else { | 2088 | } else { |
2070 | struct ieee80211_supported_band *sband; | 2089 | struct ieee80211_supported_band *sband; |
2071 | 2090 | ||
diff --git a/net/mac80211/wme.c b/net/mac80211/wme.c index cea06e9f26f4..906f00cd6d2f 100644 --- a/net/mac80211/wme.c +++ b/net/mac80211/wme.c | |||
@@ -160,31 +160,37 @@ u16 ieee80211_select_queue(struct ieee80211_sub_if_data *sdata, | |||
160 | return ieee80211_downgrade_queue(sdata, skb); | 160 | return ieee80211_downgrade_queue(sdata, skb); |
161 | } | 161 | } |
162 | 162 | ||
163 | /** | ||
164 | * ieee80211_set_qos_hdr - Fill in the QoS header if there is one. | ||
165 | * | ||
166 | * @sdata: local subif | ||
167 | * @skb: packet to be updated | ||
168 | */ | ||
163 | void ieee80211_set_qos_hdr(struct ieee80211_sub_if_data *sdata, | 169 | void ieee80211_set_qos_hdr(struct ieee80211_sub_if_data *sdata, |
164 | struct sk_buff *skb) | 170 | struct sk_buff *skb) |
165 | { | 171 | { |
166 | struct ieee80211_hdr *hdr = (void *)skb->data; | 172 | struct ieee80211_hdr *hdr = (void *)skb->data; |
167 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 173 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
174 | u8 *p; | ||
175 | u8 ack_policy, tid; | ||
168 | 176 | ||
169 | /* Fill in the QoS header if there is one. */ | 177 | if (!ieee80211_is_data_qos(hdr->frame_control)) |
170 | if (ieee80211_is_data_qos(hdr->frame_control)) { | 178 | return; |
171 | u8 *p = ieee80211_get_qos_ctl(hdr); | ||
172 | u8 ack_policy, tid; | ||
173 | |||
174 | tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK; | ||
175 | 179 | ||
176 | /* preserve EOSP bit */ | 180 | p = ieee80211_get_qos_ctl(hdr); |
177 | ack_policy = *p & IEEE80211_QOS_CTL_EOSP; | 181 | tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK; |
178 | 182 | ||
179 | if (is_multicast_ether_addr(hdr->addr1) || | 183 | /* preserve EOSP bit */ |
180 | sdata->noack_map & BIT(tid)) { | 184 | ack_policy = *p & IEEE80211_QOS_CTL_EOSP; |
181 | ack_policy |= IEEE80211_QOS_CTL_ACK_POLICY_NOACK; | ||
182 | info->flags |= IEEE80211_TX_CTL_NO_ACK; | ||
183 | } | ||
184 | 185 | ||
185 | /* qos header is 2 bytes */ | 186 | if (is_multicast_ether_addr(hdr->addr1) || |
186 | *p++ = ack_policy | tid; | 187 | sdata->noack_map & BIT(tid)) { |
187 | *p = ieee80211_vif_is_mesh(&sdata->vif) ? | 188 | ack_policy |= IEEE80211_QOS_CTL_ACK_POLICY_NOACK; |
188 | (IEEE80211_QOS_CTL_MESH_CONTROL_PRESENT >> 8) : 0; | 189 | info->flags |= IEEE80211_TX_CTL_NO_ACK; |
189 | } | 190 | } |
191 | |||
192 | /* qos header is 2 bytes */ | ||
193 | *p++ = ack_policy | tid; | ||
194 | *p = ieee80211_vif_is_mesh(&sdata->vif) ? | ||
195 | (IEEE80211_QOS_CTL_MESH_CONTROL_PRESENT >> 8) : 0; | ||
190 | } | 196 | } |