Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'mac80211-for-davem-2017-06-02' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211

Johannes Berg says:

====================
Just two fixes:
* fix the per-CPU drop counters to not be added to the
rx_packets counter, but really the drop counter
* fix TX aggregation start/stop callback races by setting
bits instead of allocating and queueing an skb
====================

Signed-off-by: David S. Miller <davem@davemloft.net>

+88 -117
+68 -92
net/mac80211/agg-tx.c
··· 7 7 * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> 8 8 * Copyright 2007, Michael Wu <flamingice@sourmilk.net> 9 9 * Copyright 2007-2010, Intel Corporation 10 - * Copyright(c) 2015 Intel Deutschland GmbH 10 + * Copyright(c) 2015-2017 Intel Deutschland GmbH 11 11 * 12 12 * This program is free software; you can redistribute it and/or modify 13 13 * it under the terms of the GNU General Public License version 2 as ··· 741 741 ieee80211_agg_start_txq(sta, tid, true); 742 742 } 743 743 744 - void ieee80211_start_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u16 tid) 744 + void ieee80211_start_tx_ba_cb(struct sta_info *sta, int tid, 745 + struct tid_ampdu_tx *tid_tx) 746 + { 747 + struct ieee80211_sub_if_data *sdata = sta->sdata; 748 + struct ieee80211_local *local = sdata->local; 749 + 750 + if (WARN_ON(test_and_set_bit(HT_AGG_STATE_DRV_READY, &tid_tx->state))) 751 + return; 752 + 753 + if (test_bit(HT_AGG_STATE_RESPONSE_RECEIVED, &tid_tx->state)) 754 + ieee80211_agg_tx_operational(local, sta, tid); 755 + } 756 + 757 + static struct tid_ampdu_tx * 758 + ieee80211_lookup_tid_tx(struct ieee80211_sub_if_data *sdata, 759 + const u8 *ra, u16 tid, struct sta_info **sta) 760 + { 761 + struct tid_ampdu_tx *tid_tx; 762 + 763 + if (tid >= IEEE80211_NUM_TIDS) { 764 + ht_dbg(sdata, "Bad TID value: tid = %d (>= %d)\n", 765 + tid, IEEE80211_NUM_TIDS); 766 + return NULL; 767 + } 768 + 769 + *sta = sta_info_get_bss(sdata, ra); 770 + if (!*sta) { 771 + ht_dbg(sdata, "Could not find station: %pM\n", ra); 772 + return NULL; 773 + } 774 + 775 + tid_tx = rcu_dereference((*sta)->ampdu_mlme.tid_tx[tid]); 776 + 777 + if (WARN_ON(!tid_tx)) 778 + ht_dbg(sdata, "addBA was not requested!\n"); 779 + 780 + return tid_tx; 781 + } 782 + 783 + void ieee80211_start_tx_ba_cb_irqsafe(struct ieee80211_vif *vif, 784 + const u8 *ra, u16 tid) 745 785 { 746 786 struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); 747 787 struct ieee80211_local *local = sdata->local; ··· 790 750 791 751 trace_api_start_tx_ba_cb(sdata, ra, tid); 792 752 793 - if (tid >= IEEE80211_NUM_TIDS) { 794 - ht_dbg(sdata, "Bad TID value: tid = %d (>= %d)\n", 795 - tid, IEEE80211_NUM_TIDS); 796 - return; 797 - } 753 + rcu_read_lock(); 754 + tid_tx = ieee80211_lookup_tid_tx(sdata, ra, tid, &sta); 755 + if (!tid_tx) 756 + goto out; 798 757 799 - mutex_lock(&local->sta_mtx); 800 - sta = sta_info_get_bss(sdata, ra); 801 - if (!sta) { 802 - mutex_unlock(&local->sta_mtx); 803 - ht_dbg(sdata, "Could not find station: %pM\n", ra); 804 - return; 805 - } 806 - 807 - mutex_lock(&sta->ampdu_mlme.mtx); 808 - tid_tx = rcu_dereference_protected_tid_tx(sta, tid); 809 - 810 - if (WARN_ON(!tid_tx)) { 811 - ht_dbg(sdata, "addBA was not requested!\n"); 812 - goto unlock; 813 - } 814 - 815 - if (WARN_ON(test_and_set_bit(HT_AGG_STATE_DRV_READY, &tid_tx->state))) 816 - goto unlock; 817 - 818 - if (test_bit(HT_AGG_STATE_RESPONSE_RECEIVED, &tid_tx->state)) 819 - ieee80211_agg_tx_operational(local, sta, tid); 820 - 821 - unlock: 822 - mutex_unlock(&sta->ampdu_mlme.mtx); 823 - mutex_unlock(&local->sta_mtx); 824 - } 825 - 826 - void ieee80211_start_tx_ba_cb_irqsafe(struct ieee80211_vif *vif, 827 - const u8 *ra, u16 tid) 828 - { 829 - struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); 830 - struct ieee80211_local *local = sdata->local; 831 - struct ieee80211_ra_tid *ra_tid; 832 - struct sk_buff *skb = dev_alloc_skb(0); 833 - 834 - if (unlikely(!skb)) 835 - return; 836 - 837 - ra_tid = (struct ieee80211_ra_tid *) &skb->cb; 838 - memcpy(&ra_tid->ra, ra, ETH_ALEN); 839 - ra_tid->tid = tid; 840 - 841 - skb->pkt_type = IEEE80211_SDATA_QUEUE_AGG_START; 842 - skb_queue_tail(&sdata->skb_queue, skb); 843 - ieee80211_queue_work(&local->hw, &sdata->work); 758 + set_bit(HT_AGG_STATE_START_CB, &tid_tx->state); 759 + ieee80211_queue_work(&local->hw, &sta->ampdu_mlme.work); 760 + out: 761 + rcu_read_unlock(); 844 762 } 845 763 EXPORT_SYMBOL(ieee80211_start_tx_ba_cb_irqsafe); 846 764 ··· 858 860 } 859 861 EXPORT_SYMBOL(ieee80211_stop_tx_ba_session); 860 862 861 - void ieee80211_stop_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u8 tid) 863 + void ieee80211_stop_tx_ba_cb(struct sta_info *sta, int tid, 864 + struct tid_ampdu_tx *tid_tx) 862 865 { 863 - struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); 864 - struct ieee80211_local *local = sdata->local; 865 - struct sta_info *sta; 866 - struct tid_ampdu_tx *tid_tx; 866 + struct ieee80211_sub_if_data *sdata = sta->sdata; 867 867 bool send_delba = false; 868 868 869 - trace_api_stop_tx_ba_cb(sdata, ra, tid); 869 + ht_dbg(sdata, "Stopping Tx BA session for %pM tid %d\n", 870 + sta->sta.addr, tid); 870 871 871 - if (tid >= IEEE80211_NUM_TIDS) { 872 - ht_dbg(sdata, "Bad TID value: tid = %d (>= %d)\n", 873 - tid, IEEE80211_NUM_TIDS); 874 - return; 875 - } 876 - 877 - ht_dbg(sdata, "Stopping Tx BA session for %pM tid %d\n", ra, tid); 878 - 879 - mutex_lock(&local->sta_mtx); 880 - 881 - sta = sta_info_get_bss(sdata, ra); 882 - if (!sta) { 883 - ht_dbg(sdata, "Could not find station: %pM\n", ra); 884 - goto unlock; 885 - } 886 - 887 - mutex_lock(&sta->ampdu_mlme.mtx); 888 872 spin_lock_bh(&sta->lock); 889 - tid_tx = rcu_dereference_protected_tid_tx(sta, tid); 890 873 891 - if (!tid_tx || !test_bit(HT_AGG_STATE_STOPPING, &tid_tx->state)) { 874 + if (!test_bit(HT_AGG_STATE_STOPPING, &tid_tx->state)) { 892 875 ht_dbg(sdata, 893 876 "unexpected callback to A-MPDU stop for %pM tid %d\n", 894 877 sta->sta.addr, tid); ··· 885 906 spin_unlock_bh(&sta->lock); 886 907 887 908 if (send_delba) 888 - ieee80211_send_delba(sdata, ra, tid, 909 + ieee80211_send_delba(sdata, sta->sta.addr, tid, 889 910 WLAN_BACK_INITIATOR, WLAN_REASON_QSTA_NOT_USE); 890 - 891 - mutex_unlock(&sta->ampdu_mlme.mtx); 892 - unlock: 893 - mutex_unlock(&local->sta_mtx); 894 911 } 895 912 896 913 void ieee80211_stop_tx_ba_cb_irqsafe(struct ieee80211_vif *vif, ··· 894 919 { 895 920 struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); 896 921 struct ieee80211_local *local = sdata->local; 897 - struct ieee80211_ra_tid *ra_tid; 898 - struct sk_buff *skb = dev_alloc_skb(0); 922 + struct sta_info *sta; 923 + struct tid_ampdu_tx *tid_tx; 899 924 900 - if (unlikely(!skb)) 901 - return; 925 + trace_api_stop_tx_ba_cb(sdata, ra, tid); 902 926 903 - ra_tid = (struct ieee80211_ra_tid *) &skb->cb; 904 - memcpy(&ra_tid->ra, ra, ETH_ALEN); 905 - ra_tid->tid = tid; 927 + rcu_read_lock(); 928 + tid_tx = ieee80211_lookup_tid_tx(sdata, ra, tid, &sta); 929 + if (!tid_tx) 930 + goto out; 906 931 907 - skb->pkt_type = IEEE80211_SDATA_QUEUE_AGG_STOP; 908 - skb_queue_tail(&sdata->skb_queue, skb); 909 - ieee80211_queue_work(&local->hw, &sdata->work); 932 + set_bit(HT_AGG_STATE_STOP_CB, &tid_tx->state); 933 + ieee80211_queue_work(&local->hw, &sta->ampdu_mlme.work); 934 + out: 935 + rcu_read_unlock(); 910 936 } 911 937 EXPORT_SYMBOL(ieee80211_stop_tx_ba_cb_irqsafe); 912 938
+12 -4
net/mac80211/ht.c
··· 7 7 * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz> 8 8 * Copyright 2007, Michael Wu <flamingice@sourmilk.net> 9 9 * Copyright 2007-2010, Intel Corporation 10 + * Copyright 2017 Intel Deutschland GmbH 10 11 * 11 12 * This program is free software; you can redistribute it and/or modify 12 13 * it under the terms of the GNU General Public License version 2 as ··· 290 289 { 291 290 int i; 292 291 293 - cancel_work_sync(&sta->ampdu_mlme.work); 294 - 295 292 for (i = 0; i < IEEE80211_NUM_TIDS; i++) { 296 293 __ieee80211_stop_tx_ba_session(sta, i, reason); 297 294 __ieee80211_stop_rx_ba_session(sta, i, WLAN_BACK_RECIPIENT, ··· 297 298 reason != AGG_STOP_DESTROY_STA && 298 299 reason != AGG_STOP_PEER_REQUEST); 299 300 } 301 + 302 + /* stopping might queue the work again - so cancel only afterwards */ 303 + cancel_work_sync(&sta->ampdu_mlme.work); 300 304 } 301 305 302 306 void ieee80211_ba_session_work(struct work_struct *work) ··· 354 352 spin_unlock_bh(&sta->lock); 355 353 356 354 tid_tx = rcu_dereference_protected_tid_tx(sta, tid); 357 - if (tid_tx && test_and_clear_bit(HT_AGG_STATE_WANT_STOP, 358 - &tid_tx->state)) 355 + if (!tid_tx) 356 + continue; 357 + 358 + if (test_and_clear_bit(HT_AGG_STATE_START_CB, &tid_tx->state)) 359 + ieee80211_start_tx_ba_cb(sta, tid, tid_tx); 360 + if (test_and_clear_bit(HT_AGG_STATE_WANT_STOP, &tid_tx->state)) 359 361 ___ieee80211_stop_tx_ba_session(sta, tid, 360 362 AGG_STOP_LOCAL_REQUEST); 363 + if (test_and_clear_bit(HT_AGG_STATE_STOP_CB, &tid_tx->state)) 364 + ieee80211_stop_tx_ba_cb(sta, tid, tid_tx); 361 365 } 362 366 mutex_unlock(&sta->ampdu_mlme.mtx); 363 367 }
+4 -10
net/mac80211/ieee80211_i.h
··· 1036 1036 1037 1037 enum sdata_queue_type { 1038 1038 IEEE80211_SDATA_QUEUE_TYPE_FRAME = 0, 1039 - IEEE80211_SDATA_QUEUE_AGG_START = 1, 1040 - IEEE80211_SDATA_QUEUE_AGG_STOP = 2, 1041 1039 IEEE80211_SDATA_QUEUE_RX_AGG_START = 3, 1042 1040 IEEE80211_SDATA_QUEUE_RX_AGG_STOP = 4, 1043 1041 }; ··· 1425 1427 return local->hw.wiphy->bands[band]; 1426 1428 } 1427 1429 1428 - /* this struct represents 802.11n's RA/TID combination */ 1429 - struct ieee80211_ra_tid { 1430 - u8 ra[ETH_ALEN]; 1431 - u16 tid; 1432 - }; 1433 - 1434 1430 /* this struct holds the value parsing from channel switch IE */ 1435 1431 struct ieee80211_csa_ie { 1436 1432 struct cfg80211_chan_def chandef; ··· 1786 1794 enum ieee80211_agg_stop_reason reason); 1787 1795 int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, 1788 1796 enum ieee80211_agg_stop_reason reason); 1789 - void ieee80211_start_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u16 tid); 1790 - void ieee80211_stop_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u8 tid); 1797 + void ieee80211_start_tx_ba_cb(struct sta_info *sta, int tid, 1798 + struct tid_ampdu_tx *tid_tx); 1799 + void ieee80211_stop_tx_ba_cb(struct sta_info *sta, int tid, 1800 + struct tid_ampdu_tx *tid_tx); 1791 1801 void ieee80211_ba_session_work(struct work_struct *work); 1792 1802 void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid); 1793 1803 void ieee80211_release_reorder_timeout(struct sta_info *sta, int tid);
+1 -10
net/mac80211/iface.c
··· 1237 1237 struct ieee80211_local *local = sdata->local; 1238 1238 struct sk_buff *skb; 1239 1239 struct sta_info *sta; 1240 - struct ieee80211_ra_tid *ra_tid; 1241 1240 struct ieee80211_rx_agg *rx_agg; 1242 1241 1243 1242 if (!ieee80211_sdata_running(sdata)) ··· 1252 1253 while ((skb = skb_dequeue(&sdata->skb_queue))) { 1253 1254 struct ieee80211_mgmt *mgmt = (void *)skb->data; 1254 1255 1255 - if (skb->pkt_type == IEEE80211_SDATA_QUEUE_AGG_START) { 1256 - ra_tid = (void *)&skb->cb; 1257 - ieee80211_start_tx_ba_cb(&sdata->vif, ra_tid->ra, 1258 - ra_tid->tid); 1259 - } else if (skb->pkt_type == IEEE80211_SDATA_QUEUE_AGG_STOP) { 1260 - ra_tid = (void *)&skb->cb; 1261 - ieee80211_stop_tx_ba_cb(&sdata->vif, ra_tid->ra, 1262 - ra_tid->tid); 1263 - } else if (skb->pkt_type == IEEE80211_SDATA_QUEUE_RX_AGG_START) { 1256 + if (skb->pkt_type == IEEE80211_SDATA_QUEUE_RX_AGG_START) { 1264 1257 rx_agg = (void *)&skb->cb; 1265 1258 mutex_lock(&local->sta_mtx); 1266 1259 sta = sta_info_get_bss(sdata, rx_agg->addr);
+1 -1
net/mac80211/sta_info.c
··· 2155 2155 struct ieee80211_sta_rx_stats *cpurxs; 2156 2156 2157 2157 cpurxs = per_cpu_ptr(sta->pcpu_rx_stats, cpu); 2158 - sinfo->rx_packets += cpurxs->dropped; 2158 + sinfo->rx_dropped_misc += cpurxs->dropped; 2159 2159 } 2160 2160 } 2161 2161
+2
net/mac80211/sta_info.h
··· 116 116 #define HT_AGG_STATE_STOPPING 3 117 117 #define HT_AGG_STATE_WANT_START 4 118 118 #define HT_AGG_STATE_WANT_STOP 5 119 + #define HT_AGG_STATE_START_CB 6 120 + #define HT_AGG_STATE_STOP_CB 7 119 121 120 122 enum ieee80211_agg_stop_reason { 121 123 AGG_STOP_DECLINED,