diff options
author | John W. Linville <linville@tuxdriver.com> | 2014-12-04 11:29:10 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2014-12-04 11:29:10 -0500 |
commit | de51f1649ab77f9ad17bdad581a326cbf6e71b49 (patch) | |
tree | 82aa375e132b3c639afe239c4e49363636199827 /net/mac80211 | |
parent | 04bb7ecf8854186f47fb1ea321fc77e7bc931993 (diff) | |
parent | f027c2aca0cf43e0f15fc8de8841f7b566163d94 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next
Johannes Berg <johannes@sipsolutions.net> says:
"This time I have Felix's no-status rate control work, which will allow
drivers to work better with rate control even if they don't have perfect
status reporting. In addition to this, a small hwsim fix from Patrik,
one of the regulatory patches from Arik, and a number of cleanups and
fixes I did myself.
Of note is a patch where I disable CFG80211_WEXT so that compatibility
is no longer selectable - this is intended as a wake-up call for anyone
who's still using it, and is still easily worked around (it's a one-line
patch) before we fully remove the code as well in the future."
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211')
-rw-r--r-- | net/mac80211/chan.c | 23 | ||||
-rw-r--r-- | net/mac80211/iface.c | 1 | ||||
-rw-r--r-- | net/mac80211/mlme.c | 24 | ||||
-rw-r--r-- | net/mac80211/rate.c | 3 | ||||
-rw-r--r-- | net/mac80211/rate.h | 24 | ||||
-rw-r--r-- | net/mac80211/rc80211_minstrel.c | 5 | ||||
-rw-r--r-- | net/mac80211/rc80211_minstrel_ht.c | 15 | ||||
-rw-r--r-- | net/mac80211/status.c | 113 | ||||
-rw-r--r-- | net/mac80211/trace.h | 6 | ||||
-rw-r--r-- | net/mac80211/tx.c | 2 | ||||
-rw-r--r-- | net/mac80211/util.c | 11 |
11 files changed, 180 insertions, 47 deletions
diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c index c7c514220298..5d6dae9e4aac 100644 --- a/net/mac80211/chan.c +++ b/net/mac80211/chan.c | |||
@@ -932,6 +932,21 @@ ieee80211_vif_chanctx_reservation_complete(struct ieee80211_sub_if_data *sdata) | |||
932 | } | 932 | } |
933 | } | 933 | } |
934 | 934 | ||
935 | static void | ||
936 | ieee80211_vif_update_chandef(struct ieee80211_sub_if_data *sdata, | ||
937 | const struct cfg80211_chan_def *chandef) | ||
938 | { | ||
939 | struct ieee80211_sub_if_data *vlan; | ||
940 | |||
941 | sdata->vif.bss_conf.chandef = *chandef; | ||
942 | |||
943 | if (sdata->vif.type != NL80211_IFTYPE_AP) | ||
944 | return; | ||
945 | |||
946 | list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) | ||
947 | vlan->vif.bss_conf.chandef = *chandef; | ||
948 | } | ||
949 | |||
935 | static int | 950 | static int |
936 | ieee80211_vif_use_reserved_reassign(struct ieee80211_sub_if_data *sdata) | 951 | ieee80211_vif_use_reserved_reassign(struct ieee80211_sub_if_data *sdata) |
937 | { | 952 | { |
@@ -994,7 +1009,7 @@ ieee80211_vif_use_reserved_reassign(struct ieee80211_sub_if_data *sdata) | |||
994 | if (sdata->vif.bss_conf.chandef.width != sdata->reserved_chandef.width) | 1009 | if (sdata->vif.bss_conf.chandef.width != sdata->reserved_chandef.width) |
995 | changed = BSS_CHANGED_BANDWIDTH; | 1010 | changed = BSS_CHANGED_BANDWIDTH; |
996 | 1011 | ||
997 | sdata->vif.bss_conf.chandef = sdata->reserved_chandef; | 1012 | ieee80211_vif_update_chandef(sdata, &sdata->reserved_chandef); |
998 | 1013 | ||
999 | if (changed) | 1014 | if (changed) |
1000 | ieee80211_bss_info_change_notify(sdata, changed); | 1015 | ieee80211_bss_info_change_notify(sdata, changed); |
@@ -1336,7 +1351,7 @@ static int ieee80211_vif_use_reserved_switch(struct ieee80211_local *local) | |||
1336 | sdata->reserved_chandef.width) | 1351 | sdata->reserved_chandef.width) |
1337 | changed = BSS_CHANGED_BANDWIDTH; | 1352 | changed = BSS_CHANGED_BANDWIDTH; |
1338 | 1353 | ||
1339 | sdata->vif.bss_conf.chandef = sdata->reserved_chandef; | 1354 | ieee80211_vif_update_chandef(sdata, &sdata->reserved_chandef); |
1340 | if (changed) | 1355 | if (changed) |
1341 | ieee80211_bss_info_change_notify(sdata, | 1356 | ieee80211_bss_info_change_notify(sdata, |
1342 | changed); | 1357 | changed); |
@@ -1507,7 +1522,7 @@ int ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata, | |||
1507 | goto out; | 1522 | goto out; |
1508 | } | 1523 | } |
1509 | 1524 | ||
1510 | sdata->vif.bss_conf.chandef = *chandef; | 1525 | ieee80211_vif_update_chandef(sdata, chandef); |
1511 | 1526 | ||
1512 | ret = ieee80211_assign_vif_chanctx(sdata, ctx); | 1527 | ret = ieee80211_assign_vif_chanctx(sdata, ctx); |
1513 | if (ret) { | 1528 | if (ret) { |
@@ -1649,7 +1664,7 @@ int ieee80211_vif_change_bandwidth(struct ieee80211_sub_if_data *sdata, | |||
1649 | break; | 1664 | break; |
1650 | } | 1665 | } |
1651 | 1666 | ||
1652 | sdata->vif.bss_conf.chandef = *chandef; | 1667 | ieee80211_vif_update_chandef(sdata, chandef); |
1653 | 1668 | ||
1654 | ieee80211_recalc_chanctx_chantype(local, ctx); | 1669 | ieee80211_recalc_chanctx_chantype(local, ctx); |
1655 | 1670 | ||
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 538fe4ef5c85..417355390873 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -520,6 +520,7 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up) | |||
520 | sdata->vif.cab_queue = master->vif.cab_queue; | 520 | sdata->vif.cab_queue = master->vif.cab_queue; |
521 | memcpy(sdata->vif.hw_queue, master->vif.hw_queue, | 521 | memcpy(sdata->vif.hw_queue, master->vif.hw_queue, |
522 | sizeof(sdata->vif.hw_queue)); | 522 | sizeof(sdata->vif.hw_queue)); |
523 | sdata->vif.bss_conf.chandef = master->vif.bss_conf.chandef; | ||
523 | break; | 524 | break; |
524 | } | 525 | } |
525 | case NL80211_IFTYPE_AP: | 526 | case NL80211_IFTYPE_AP: |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index ba06cd003375..75a9bf50207e 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -552,13 +552,17 @@ static void ieee80211_add_vht_ie(struct ieee80211_sub_if_data *sdata, | |||
552 | cap = vht_cap.cap; | 552 | cap = vht_cap.cap; |
553 | 553 | ||
554 | if (sdata->u.mgd.flags & IEEE80211_STA_DISABLE_80P80MHZ) { | 554 | if (sdata->u.mgd.flags & IEEE80211_STA_DISABLE_80P80MHZ) { |
555 | cap &= ~IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ; | 555 | u32 bw = cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK; |
556 | cap |= IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ; | 556 | |
557 | cap &= ~IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK; | ||
558 | if (bw == IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ || | ||
559 | bw == IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ) | ||
560 | cap |= IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ; | ||
557 | } | 561 | } |
558 | 562 | ||
559 | if (sdata->u.mgd.flags & IEEE80211_STA_DISABLE_160MHZ) { | 563 | if (sdata->u.mgd.flags & IEEE80211_STA_DISABLE_160MHZ) { |
560 | cap &= ~IEEE80211_VHT_CAP_SHORT_GI_160; | 564 | cap &= ~IEEE80211_VHT_CAP_SHORT_GI_160; |
561 | cap &= ~IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ; | 565 | cap &= ~IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK; |
562 | } | 566 | } |
563 | 567 | ||
564 | /* | 568 | /* |
@@ -2263,9 +2267,7 @@ static void ieee80211_mgd_probe_ap(struct ieee80211_sub_if_data *sdata, | |||
2263 | "detected beacon loss from AP (missed %d beacons) - probing\n", | 2267 | "detected beacon loss from AP (missed %d beacons) - probing\n", |
2264 | beacon_loss_count); | 2268 | beacon_loss_count); |
2265 | 2269 | ||
2266 | ieee80211_cqm_rssi_notify(&sdata->vif, | 2270 | ieee80211_cqm_beacon_loss_notify(&sdata->vif, GFP_KERNEL); |
2267 | NL80211_CQM_RSSI_BEACON_LOSS_EVENT, | ||
2268 | GFP_KERNEL); | ||
2269 | } | 2271 | } |
2270 | 2272 | ||
2271 | /* | 2273 | /* |
@@ -4898,3 +4900,13 @@ void ieee80211_cqm_rssi_notify(struct ieee80211_vif *vif, | |||
4898 | cfg80211_cqm_rssi_notify(sdata->dev, rssi_event, gfp); | 4900 | cfg80211_cqm_rssi_notify(sdata->dev, rssi_event, gfp); |
4899 | } | 4901 | } |
4900 | EXPORT_SYMBOL(ieee80211_cqm_rssi_notify); | 4902 | EXPORT_SYMBOL(ieee80211_cqm_rssi_notify); |
4903 | |||
4904 | void ieee80211_cqm_beacon_loss_notify(struct ieee80211_vif *vif, gfp_t gfp) | ||
4905 | { | ||
4906 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); | ||
4907 | |||
4908 | trace_api_cqm_beacon_loss_notify(sdata->local, sdata); | ||
4909 | |||
4910 | cfg80211_cqm_beacon_loss_notify(sdata->dev, gfp); | ||
4911 | } | ||
4912 | EXPORT_SYMBOL(ieee80211_cqm_beacon_loss_notify); | ||
diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c index 08ab7d6d1517..d53355b011f5 100644 --- a/net/mac80211/rate.c +++ b/net/mac80211/rate.c | |||
@@ -446,7 +446,8 @@ static void rate_fixup_ratelist(struct ieee80211_vif *vif, | |||
446 | * | 446 | * |
447 | * XXX: Should this check all retry rates? | 447 | * XXX: Should this check all retry rates? |
448 | */ | 448 | */ |
449 | if (!(rates[0].flags & IEEE80211_TX_RC_MCS)) { | 449 | if (!(rates[0].flags & |
450 | (IEEE80211_TX_RC_MCS | IEEE80211_TX_RC_VHT_MCS))) { | ||
450 | u32 basic_rates = vif->bss_conf.basic_rates; | 451 | u32 basic_rates = vif->bss_conf.basic_rates; |
451 | s8 baserate = basic_rates ? ffs(basic_rates) - 1 : 0; | 452 | s8 baserate = basic_rates ? ffs(basic_rates) - 1 : 0; |
452 | 453 | ||
diff --git a/net/mac80211/rate.h b/net/mac80211/rate.h index 18babe302832..38652f09feaf 100644 --- a/net/mac80211/rate.h +++ b/net/mac80211/rate.h | |||
@@ -37,13 +37,35 @@ static inline void rate_control_tx_status(struct ieee80211_local *local, | |||
37 | struct rate_control_ref *ref = local->rate_ctrl; | 37 | struct rate_control_ref *ref = local->rate_ctrl; |
38 | struct ieee80211_sta *ista = &sta->sta; | 38 | struct ieee80211_sta *ista = &sta->sta; |
39 | void *priv_sta = sta->rate_ctrl_priv; | 39 | void *priv_sta = sta->rate_ctrl_priv; |
40 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
40 | 41 | ||
41 | if (!ref || !test_sta_flag(sta, WLAN_STA_RATE_CONTROL)) | 42 | if (!ref || !test_sta_flag(sta, WLAN_STA_RATE_CONTROL)) |
42 | return; | 43 | return; |
43 | 44 | ||
44 | ref->ops->tx_status(ref->priv, sband, ista, priv_sta, skb); | 45 | if (ref->ops->tx_status) |
46 | ref->ops->tx_status(ref->priv, sband, ista, priv_sta, skb); | ||
47 | else | ||
48 | ref->ops->tx_status_noskb(ref->priv, sband, ista, priv_sta, info); | ||
45 | } | 49 | } |
46 | 50 | ||
51 | static inline void | ||
52 | rate_control_tx_status_noskb(struct ieee80211_local *local, | ||
53 | struct ieee80211_supported_band *sband, | ||
54 | struct sta_info *sta, | ||
55 | struct ieee80211_tx_info *info) | ||
56 | { | ||
57 | struct rate_control_ref *ref = local->rate_ctrl; | ||
58 | struct ieee80211_sta *ista = &sta->sta; | ||
59 | void *priv_sta = sta->rate_ctrl_priv; | ||
60 | |||
61 | if (!ref || !test_sta_flag(sta, WLAN_STA_RATE_CONTROL)) | ||
62 | return; | ||
63 | |||
64 | if (WARN_ON_ONCE(!ref->ops->tx_status_noskb)) | ||
65 | return; | ||
66 | |||
67 | ref->ops->tx_status_noskb(ref->priv, sband, ista, priv_sta, info); | ||
68 | } | ||
47 | 69 | ||
48 | static inline void rate_control_rate_init(struct sta_info *sta) | 70 | static inline void rate_control_rate_init(struct sta_info *sta) |
49 | { | 71 | { |
diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c index c2b91bf47f6d..d51f6b1c549b 100644 --- a/net/mac80211/rc80211_minstrel.c +++ b/net/mac80211/rc80211_minstrel.c | |||
@@ -223,11 +223,10 @@ minstrel_update_stats(struct minstrel_priv *mp, struct minstrel_sta_info *mi) | |||
223 | static void | 223 | static void |
224 | minstrel_tx_status(void *priv, struct ieee80211_supported_band *sband, | 224 | minstrel_tx_status(void *priv, struct ieee80211_supported_band *sband, |
225 | struct ieee80211_sta *sta, void *priv_sta, | 225 | struct ieee80211_sta *sta, void *priv_sta, |
226 | struct sk_buff *skb) | 226 | struct ieee80211_tx_info *info) |
227 | { | 227 | { |
228 | struct minstrel_priv *mp = priv; | 228 | struct minstrel_priv *mp = priv; |
229 | struct minstrel_sta_info *mi = priv_sta; | 229 | struct minstrel_sta_info *mi = priv_sta; |
230 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
231 | struct ieee80211_tx_rate *ar = info->status.rates; | 230 | struct ieee80211_tx_rate *ar = info->status.rates; |
232 | int i, ndx; | 231 | int i, ndx; |
233 | int success; | 232 | int success; |
@@ -674,7 +673,7 @@ static u32 minstrel_get_expected_throughput(void *priv_sta) | |||
674 | 673 | ||
675 | const struct rate_control_ops mac80211_minstrel = { | 674 | const struct rate_control_ops mac80211_minstrel = { |
676 | .name = "minstrel", | 675 | .name = "minstrel", |
677 | .tx_status = minstrel_tx_status, | 676 | .tx_status_noskb = minstrel_tx_status, |
678 | .get_rate = minstrel_get_rate, | 677 | .get_rate = minstrel_get_rate, |
679 | .rate_init = minstrel_rate_init, | 678 | .rate_init = minstrel_rate_init, |
680 | .alloc = minstrel_alloc, | 679 | .alloc = minstrel_alloc, |
diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c index 62ff7cfb2723..b52996aca4f1 100644 --- a/net/mac80211/rc80211_minstrel_ht.c +++ b/net/mac80211/rc80211_minstrel_ht.c | |||
@@ -709,11 +709,10 @@ minstrel_aggr_check(struct ieee80211_sta *pubsta, struct sk_buff *skb) | |||
709 | static void | 709 | static void |
710 | minstrel_ht_tx_status(void *priv, struct ieee80211_supported_band *sband, | 710 | minstrel_ht_tx_status(void *priv, struct ieee80211_supported_band *sband, |
711 | struct ieee80211_sta *sta, void *priv_sta, | 711 | struct ieee80211_sta *sta, void *priv_sta, |
712 | struct sk_buff *skb) | 712 | struct ieee80211_tx_info *info) |
713 | { | 713 | { |
714 | struct minstrel_ht_sta_priv *msp = priv_sta; | 714 | struct minstrel_ht_sta_priv *msp = priv_sta; |
715 | struct minstrel_ht_sta *mi = &msp->ht; | 715 | struct minstrel_ht_sta *mi = &msp->ht; |
716 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
717 | struct ieee80211_tx_rate *ar = info->status.rates; | 716 | struct ieee80211_tx_rate *ar = info->status.rates; |
718 | struct minstrel_rate_stats *rate, *rate2; | 717 | struct minstrel_rate_stats *rate, *rate2; |
719 | struct minstrel_priv *mp = priv; | 718 | struct minstrel_priv *mp = priv; |
@@ -721,7 +720,8 @@ minstrel_ht_tx_status(void *priv, struct ieee80211_supported_band *sband, | |||
721 | int i; | 720 | int i; |
722 | 721 | ||
723 | if (!msp->is_ht) | 722 | if (!msp->is_ht) |
724 | return mac80211_minstrel.tx_status(priv, sband, sta, &msp->legacy, skb); | 723 | return mac80211_minstrel.tx_status_noskb(priv, sband, sta, |
724 | &msp->legacy, info); | ||
725 | 725 | ||
726 | /* This packet was aggregated but doesn't carry status info */ | 726 | /* This packet was aggregated but doesn't carry status info */ |
727 | if ((info->flags & IEEE80211_TX_CTL_AMPDU) && | 727 | if ((info->flags & IEEE80211_TX_CTL_AMPDU) && |
@@ -782,9 +782,6 @@ minstrel_ht_tx_status(void *priv, struct ieee80211_supported_band *sband, | |||
782 | if (time_after(jiffies, mi->stats_update + (mp->update_interval / 2 * HZ) / 1000)) { | 782 | if (time_after(jiffies, mi->stats_update + (mp->update_interval / 2 * HZ) / 1000)) { |
783 | update = true; | 783 | update = true; |
784 | minstrel_ht_update_stats(mp, mi); | 784 | minstrel_ht_update_stats(mp, mi); |
785 | if (!(info->flags & IEEE80211_TX_CTL_AMPDU) && | ||
786 | mi->max_prob_rate / MCS_GROUP_RATES != MINSTREL_CCK_GROUP) | ||
787 | minstrel_aggr_check(sta, skb); | ||
788 | } | 785 | } |
789 | 786 | ||
790 | if (update) | 787 | if (update) |
@@ -1026,6 +1023,10 @@ minstrel_ht_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta, | |||
1026 | if (!msp->is_ht) | 1023 | if (!msp->is_ht) |
1027 | return mac80211_minstrel.get_rate(priv, sta, &msp->legacy, txrc); | 1024 | return mac80211_minstrel.get_rate(priv, sta, &msp->legacy, txrc); |
1028 | 1025 | ||
1026 | if (!(info->flags & IEEE80211_TX_CTL_AMPDU) && | ||
1027 | mi->max_prob_rate / MCS_GROUP_RATES != MINSTREL_CCK_GROUP) | ||
1028 | minstrel_aggr_check(sta, txrc->skb); | ||
1029 | |||
1029 | info->flags |= mi->tx_flags; | 1030 | info->flags |= mi->tx_flags; |
1030 | minstrel_ht_check_cck_shortpreamble(mp, mi, txrc->short_preamble); | 1031 | minstrel_ht_check_cck_shortpreamble(mp, mi, txrc->short_preamble); |
1031 | 1032 | ||
@@ -1342,7 +1343,7 @@ static u32 minstrel_ht_get_expected_throughput(void *priv_sta) | |||
1342 | 1343 | ||
1343 | static const struct rate_control_ops mac80211_minstrel_ht = { | 1344 | static const struct rate_control_ops mac80211_minstrel_ht = { |
1344 | .name = "minstrel_ht", | 1345 | .name = "minstrel_ht", |
1345 | .tx_status = minstrel_ht_tx_status, | 1346 | .tx_status_noskb = minstrel_ht_tx_status, |
1346 | .get_rate = minstrel_ht_get_rate, | 1347 | .get_rate = minstrel_ht_get_rate, |
1347 | .rate_init = minstrel_ht_rate_init, | 1348 | .rate_init = minstrel_ht_rate_init, |
1348 | .rate_update = minstrel_ht_rate_update, | 1349 | .rate_update = minstrel_ht_rate_update, |
diff --git a/net/mac80211/status.c b/net/mac80211/status.c index 71de2d3866cc..bb146f377ee4 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c | |||
@@ -592,10 +592,9 @@ static void ieee80211_tx_latency_end_msrmnt(struct ieee80211_local *local, | |||
592 | #define STA_LOST_TDLS_PKT_THRESHOLD 10 | 592 | #define STA_LOST_TDLS_PKT_THRESHOLD 10 |
593 | #define STA_LOST_TDLS_PKT_TIME (10*HZ) /* 10secs since last ACK */ | 593 | #define STA_LOST_TDLS_PKT_TIME (10*HZ) /* 10secs since last ACK */ |
594 | 594 | ||
595 | static void ieee80211_lost_packet(struct sta_info *sta, struct sk_buff *skb) | 595 | static void ieee80211_lost_packet(struct sta_info *sta, |
596 | struct ieee80211_tx_info *info) | ||
596 | { | 597 | { |
597 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
598 | |||
599 | /* This packet was aggregated but doesn't carry status info */ | 598 | /* This packet was aggregated but doesn't carry status info */ |
600 | if ((info->flags & IEEE80211_TX_CTL_AMPDU) && | 599 | if ((info->flags & IEEE80211_TX_CTL_AMPDU) && |
601 | !(info->flags & IEEE80211_TX_STAT_AMPDU)) | 600 | !(info->flags & IEEE80211_TX_STAT_AMPDU)) |
@@ -622,24 +621,13 @@ static void ieee80211_lost_packet(struct sta_info *sta, struct sk_buff *skb) | |||
622 | sta->lost_packets = 0; | 621 | sta->lost_packets = 0; |
623 | } | 622 | } |
624 | 623 | ||
625 | void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | 624 | static int ieee80211_tx_get_rates(struct ieee80211_hw *hw, |
625 | struct ieee80211_tx_info *info, | ||
626 | int *retry_count) | ||
626 | { | 627 | { |
627 | struct sk_buff *skb2; | ||
628 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | ||
629 | struct ieee80211_local *local = hw_to_local(hw); | ||
630 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
631 | __le16 fc; | ||
632 | struct ieee80211_supported_band *sband; | ||
633 | struct ieee80211_sub_if_data *sdata; | ||
634 | struct net_device *prev_dev = NULL; | ||
635 | struct sta_info *sta, *tmp; | ||
636 | int retry_count = -1, i; | ||
637 | int rates_idx = -1; | 628 | int rates_idx = -1; |
638 | bool send_to_cooked; | 629 | int count = -1; |
639 | bool acked; | 630 | int i; |
640 | struct ieee80211_bar *bar; | ||
641 | int rtap_len; | ||
642 | int shift = 0; | ||
643 | 631 | ||
644 | for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { | 632 | for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { |
645 | if ((info->flags & IEEE80211_TX_CTL_AMPDU) && | 633 | if ((info->flags & IEEE80211_TX_CTL_AMPDU) && |
@@ -657,12 +645,91 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
657 | break; | 645 | break; |
658 | } | 646 | } |
659 | 647 | ||
660 | retry_count += info->status.rates[i].count; | 648 | count += info->status.rates[i].count; |
661 | } | 649 | } |
662 | rates_idx = i - 1; | 650 | rates_idx = i - 1; |
663 | 651 | ||
664 | if (retry_count < 0) | 652 | if (count < 0) |
665 | retry_count = 0; | 653 | count = 0; |
654 | |||
655 | *retry_count = count; | ||
656 | return rates_idx; | ||
657 | } | ||
658 | |||
659 | void ieee80211_tx_status_noskb(struct ieee80211_hw *hw, | ||
660 | struct ieee80211_sta *pubsta, | ||
661 | struct ieee80211_tx_info *info) | ||
662 | { | ||
663 | struct ieee80211_local *local = hw_to_local(hw); | ||
664 | struct ieee80211_supported_band *sband; | ||
665 | int retry_count; | ||
666 | int rates_idx; | ||
667 | bool acked; | ||
668 | |||
669 | rates_idx = ieee80211_tx_get_rates(hw, info, &retry_count); | ||
670 | |||
671 | sband = hw->wiphy->bands[info->band]; | ||
672 | |||
673 | acked = !!(info->flags & IEEE80211_TX_STAT_ACK); | ||
674 | if (pubsta) { | ||
675 | struct sta_info *sta; | ||
676 | |||
677 | sta = container_of(pubsta, struct sta_info, sta); | ||
678 | |||
679 | if (!acked) | ||
680 | sta->tx_retry_failed++; | ||
681 | sta->tx_retry_count += retry_count; | ||
682 | |||
683 | if (acked) { | ||
684 | sta->last_rx = jiffies; | ||
685 | |||
686 | if (sta->lost_packets) | ||
687 | sta->lost_packets = 0; | ||
688 | |||
689 | /* Track when last TDLS packet was ACKed */ | ||
690 | if (test_sta_flag(sta, WLAN_STA_TDLS_PEER_AUTH)) | ||
691 | sta->last_tdls_pkt_time = jiffies; | ||
692 | } else { | ||
693 | ieee80211_lost_packet(sta, info); | ||
694 | } | ||
695 | |||
696 | rate_control_tx_status_noskb(local, sband, sta, info); | ||
697 | } | ||
698 | |||
699 | if (acked) { | ||
700 | local->dot11TransmittedFrameCount++; | ||
701 | if (!pubsta) | ||
702 | local->dot11MulticastTransmittedFrameCount++; | ||
703 | if (retry_count > 0) | ||
704 | local->dot11RetryCount++; | ||
705 | if (retry_count > 1) | ||
706 | local->dot11MultipleRetryCount++; | ||
707 | } else { | ||
708 | local->dot11FailedCount++; | ||
709 | } | ||
710 | } | ||
711 | EXPORT_SYMBOL(ieee80211_tx_status_noskb); | ||
712 | |||
713 | void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | ||
714 | { | ||
715 | struct sk_buff *skb2; | ||
716 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | ||
717 | struct ieee80211_local *local = hw_to_local(hw); | ||
718 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
719 | __le16 fc; | ||
720 | struct ieee80211_supported_band *sband; | ||
721 | struct ieee80211_sub_if_data *sdata; | ||
722 | struct net_device *prev_dev = NULL; | ||
723 | struct sta_info *sta, *tmp; | ||
724 | int retry_count; | ||
725 | int rates_idx; | ||
726 | bool send_to_cooked; | ||
727 | bool acked; | ||
728 | struct ieee80211_bar *bar; | ||
729 | int rtap_len; | ||
730 | int shift = 0; | ||
731 | |||
732 | rates_idx = ieee80211_tx_get_rates(hw, info, &retry_count); | ||
666 | 733 | ||
667 | rcu_read_lock(); | 734 | rcu_read_lock(); |
668 | 735 | ||
@@ -767,7 +834,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
767 | if (test_sta_flag(sta, WLAN_STA_TDLS_PEER_AUTH)) | 834 | if (test_sta_flag(sta, WLAN_STA_TDLS_PEER_AUTH)) |
768 | sta->last_tdls_pkt_time = jiffies; | 835 | sta->last_tdls_pkt_time = jiffies; |
769 | } else { | 836 | } else { |
770 | ieee80211_lost_packet(sta, skb); | 837 | ieee80211_lost_packet(sta, info); |
771 | } | 838 | } |
772 | } | 839 | } |
773 | 840 | ||
diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h index 85ccfbe863db..8e461a02c6a8 100644 --- a/net/mac80211/trace.h +++ b/net/mac80211/trace.h | |||
@@ -1829,6 +1829,12 @@ TRACE_EVENT(api_cqm_rssi_notify, | |||
1829 | ) | 1829 | ) |
1830 | ); | 1830 | ); |
1831 | 1831 | ||
1832 | DEFINE_EVENT(local_sdata_evt, api_cqm_beacon_loss_notify, | ||
1833 | TP_PROTO(struct ieee80211_local *local, | ||
1834 | struct ieee80211_sub_if_data *sdata), | ||
1835 | TP_ARGS(local, sdata) | ||
1836 | ); | ||
1837 | |||
1832 | TRACE_EVENT(api_scan_completed, | 1838 | TRACE_EVENT(api_scan_completed, |
1833 | TP_PROTO(struct ieee80211_local *local, bool aborted), | 1839 | TP_PROTO(struct ieee80211_local *local, bool aborted), |
1834 | 1840 | ||
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 66ddbbeccd20..058686a721a1 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -60,7 +60,7 @@ static __le16 ieee80211_duration(struct ieee80211_tx_data *tx, | |||
60 | rcu_read_unlock(); | 60 | rcu_read_unlock(); |
61 | 61 | ||
62 | /* assume HW handles this */ | 62 | /* assume HW handles this */ |
63 | if (tx->rate.flags & IEEE80211_TX_RC_MCS) | 63 | if (tx->rate.flags & (IEEE80211_TX_RC_MCS | IEEE80211_TX_RC_VHT_MCS)) |
64 | return 0; | 64 | return 0; |
65 | 65 | ||
66 | /* uh huh? */ | 66 | /* uh huh? */ |
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index bb9664cb8831..974ebe70f5b0 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -1339,6 +1339,7 @@ static int ieee80211_build_preq_ies_band(struct ieee80211_local *local, | |||
1339 | int ext_rates_len; | 1339 | int ext_rates_len; |
1340 | int shift; | 1340 | int shift; |
1341 | u32 rate_flags; | 1341 | u32 rate_flags; |
1342 | bool have_80mhz = false; | ||
1342 | 1343 | ||
1343 | *offset = 0; | 1344 | *offset = 0; |
1344 | 1345 | ||
@@ -1467,7 +1468,15 @@ static int ieee80211_build_preq_ies_band(struct ieee80211_local *local, | |||
1467 | *offset = noffset; | 1468 | *offset = noffset; |
1468 | } | 1469 | } |
1469 | 1470 | ||
1470 | if (sband->vht_cap.vht_supported) { | 1471 | /* Check if any channel in this sband supports at least 80 MHz */ |
1472 | for (i = 0; i < sband->n_channels; i++) { | ||
1473 | if (!(sband->channels[i].flags & IEEE80211_CHAN_NO_80MHZ)) { | ||
1474 | have_80mhz = true; | ||
1475 | break; | ||
1476 | } | ||
1477 | } | ||
1478 | |||
1479 | if (sband->vht_cap.vht_supported && have_80mhz) { | ||
1471 | if (end - pos < 2 + sizeof(struct ieee80211_vht_cap)) | 1480 | if (end - pos < 2 + sizeof(struct ieee80211_vht_cap)) |
1472 | goto out_err; | 1481 | goto out_err; |
1473 | pos = ieee80211_ie_build_vht_cap(pos, &sband->vht_cap, | 1482 | pos = ieee80211_ie_build_vht_cap(pos, &sband->vht_cap, |