mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-09 14:43:16 +00:00
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 -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEExu3sM/nZ1eRSfR9Ha3t4Rpy0AB0FAlkxbE0ACgkQa3t4Rpy0 AB0vlA/8DJ/EccfrzUulYgz7N6e3eZnLV0PL5HG4QLFhS+iL71EkGMgX66PrTpJf 0J308+VuNI/B0n48NF3NOUIg57yiF8i/VulxqR1FNYXdOfLXc5gc9Ca4oSOOlzHr z+CrCm2Z4GLwAZrketrUKuQBoPL8UXY3UKp4OzQoOCk50UujszInlRzXqlLdUHIE If+lg7O+Uq9udGb0WjH845H/GkjEiy5+4rM64pCkmu+rcPhb9uXbC9JI3b3SRu2j VeXl0ShaEEGA971JdncQ20x91rpadItJgnCm0bJ+zNwxZT5JakXW+ZUJGn2EKEqw hPvlvMgBzeAeLsCaRiQJspVdNHlgUa1nNTmn2n7R7+qn6LXuI7tZcj4UdOsn/Sfa eHTHc5irAiyp3ow6MAM+HgjH4/UHMbQg6HQMitVAGFO8Lluy1F1hIijP2amO0/It rHSINcDMi0Crn2rn+2tsYlU6pSzSJFS3kg+yfooK+C+pNl+Td0vH6n6EScvsKttG X6iAykbhPpjS/TrZg4RAPkFNqa7yooXXpvoIX1xtjUFRd1xUm6IE3O/6wN/l4X34 QVyIQolw0LgWvoh3N3YZw7f9OFdc2AImnTU7XmHo6jYiZn4Y7+pO4x4OnAocw4aX SNXmqVwui7EjwGycDMohtOfFavTHC7KjoLRGBKONZXi7ZqqEKtI= =ZgHD -----END PGP SIGNATURE----- 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>
This commit is contained in:
commit
13fb6c2c7f
@ -7,7 +7,7 @@
|
||||
* Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
|
||||
* Copyright 2007, Michael Wu <flamingice@sourmilk.net>
|
||||
* Copyright 2007-2010, Intel Corporation
|
||||
* Copyright(c) 2015 Intel Deutschland GmbH
|
||||
* Copyright(c) 2015-2017 Intel Deutschland GmbH
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
@ -741,7 +741,47 @@ static void ieee80211_agg_tx_operational(struct ieee80211_local *local,
|
||||
ieee80211_agg_start_txq(sta, tid, true);
|
||||
}
|
||||
|
||||
void ieee80211_start_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u16 tid)
|
||||
void ieee80211_start_tx_ba_cb(struct sta_info *sta, int tid,
|
||||
struct tid_ampdu_tx *tid_tx)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata = sta->sdata;
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
|
||||
if (WARN_ON(test_and_set_bit(HT_AGG_STATE_DRV_READY, &tid_tx->state)))
|
||||
return;
|
||||
|
||||
if (test_bit(HT_AGG_STATE_RESPONSE_RECEIVED, &tid_tx->state))
|
||||
ieee80211_agg_tx_operational(local, sta, tid);
|
||||
}
|
||||
|
||||
static struct tid_ampdu_tx *
|
||||
ieee80211_lookup_tid_tx(struct ieee80211_sub_if_data *sdata,
|
||||
const u8 *ra, u16 tid, struct sta_info **sta)
|
||||
{
|
||||
struct tid_ampdu_tx *tid_tx;
|
||||
|
||||
if (tid >= IEEE80211_NUM_TIDS) {
|
||||
ht_dbg(sdata, "Bad TID value: tid = %d (>= %d)\n",
|
||||
tid, IEEE80211_NUM_TIDS);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*sta = sta_info_get_bss(sdata, ra);
|
||||
if (!*sta) {
|
||||
ht_dbg(sdata, "Could not find station: %pM\n", ra);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
tid_tx = rcu_dereference((*sta)->ampdu_mlme.tid_tx[tid]);
|
||||
|
||||
if (WARN_ON(!tid_tx))
|
||||
ht_dbg(sdata, "addBA was not requested!\n");
|
||||
|
||||
return tid_tx;
|
||||
}
|
||||
|
||||
void ieee80211_start_tx_ba_cb_irqsafe(struct ieee80211_vif *vif,
|
||||
const u8 *ra, u16 tid)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
@ -750,57 +790,15 @@ void ieee80211_start_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u16 tid)
|
||||
|
||||
trace_api_start_tx_ba_cb(sdata, ra, tid);
|
||||
|
||||
if (tid >= IEEE80211_NUM_TIDS) {
|
||||
ht_dbg(sdata, "Bad TID value: tid = %d (>= %d)\n",
|
||||
tid, IEEE80211_NUM_TIDS);
|
||||
return;
|
||||
}
|
||||
rcu_read_lock();
|
||||
tid_tx = ieee80211_lookup_tid_tx(sdata, ra, tid, &sta);
|
||||
if (!tid_tx)
|
||||
goto out;
|
||||
|
||||
mutex_lock(&local->sta_mtx);
|
||||
sta = sta_info_get_bss(sdata, ra);
|
||||
if (!sta) {
|
||||
mutex_unlock(&local->sta_mtx);
|
||||
ht_dbg(sdata, "Could not find station: %pM\n", ra);
|
||||
return;
|
||||
}
|
||||
|
||||
mutex_lock(&sta->ampdu_mlme.mtx);
|
||||
tid_tx = rcu_dereference_protected_tid_tx(sta, tid);
|
||||
|
||||
if (WARN_ON(!tid_tx)) {
|
||||
ht_dbg(sdata, "addBA was not requested!\n");
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
if (WARN_ON(test_and_set_bit(HT_AGG_STATE_DRV_READY, &tid_tx->state)))
|
||||
goto unlock;
|
||||
|
||||
if (test_bit(HT_AGG_STATE_RESPONSE_RECEIVED, &tid_tx->state))
|
||||
ieee80211_agg_tx_operational(local, sta, tid);
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&sta->ampdu_mlme.mtx);
|
||||
mutex_unlock(&local->sta_mtx);
|
||||
}
|
||||
|
||||
void ieee80211_start_tx_ba_cb_irqsafe(struct ieee80211_vif *vif,
|
||||
const u8 *ra, u16 tid)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
struct ieee80211_ra_tid *ra_tid;
|
||||
struct sk_buff *skb = dev_alloc_skb(0);
|
||||
|
||||
if (unlikely(!skb))
|
||||
return;
|
||||
|
||||
ra_tid = (struct ieee80211_ra_tid *) &skb->cb;
|
||||
memcpy(&ra_tid->ra, ra, ETH_ALEN);
|
||||
ra_tid->tid = tid;
|
||||
|
||||
skb->pkt_type = IEEE80211_SDATA_QUEUE_AGG_START;
|
||||
skb_queue_tail(&sdata->skb_queue, skb);
|
||||
ieee80211_queue_work(&local->hw, &sdata->work);
|
||||
set_bit(HT_AGG_STATE_START_CB, &tid_tx->state);
|
||||
ieee80211_queue_work(&local->hw, &sta->ampdu_mlme.work);
|
||||
out:
|
||||
rcu_read_unlock();
|
||||
}
|
||||
EXPORT_SYMBOL(ieee80211_start_tx_ba_cb_irqsafe);
|
||||
|
||||
@ -860,37 +858,18 @@ int ieee80211_stop_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid)
|
||||
}
|
||||
EXPORT_SYMBOL(ieee80211_stop_tx_ba_session);
|
||||
|
||||
void ieee80211_stop_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u8 tid)
|
||||
void ieee80211_stop_tx_ba_cb(struct sta_info *sta, int tid,
|
||||
struct tid_ampdu_tx *tid_tx)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
struct sta_info *sta;
|
||||
struct tid_ampdu_tx *tid_tx;
|
||||
struct ieee80211_sub_if_data *sdata = sta->sdata;
|
||||
bool send_delba = false;
|
||||
|
||||
trace_api_stop_tx_ba_cb(sdata, ra, tid);
|
||||
ht_dbg(sdata, "Stopping Tx BA session for %pM tid %d\n",
|
||||
sta->sta.addr, tid);
|
||||
|
||||
if (tid >= IEEE80211_NUM_TIDS) {
|
||||
ht_dbg(sdata, "Bad TID value: tid = %d (>= %d)\n",
|
||||
tid, IEEE80211_NUM_TIDS);
|
||||
return;
|
||||
}
|
||||
|
||||
ht_dbg(sdata, "Stopping Tx BA session for %pM tid %d\n", ra, tid);
|
||||
|
||||
mutex_lock(&local->sta_mtx);
|
||||
|
||||
sta = sta_info_get_bss(sdata, ra);
|
||||
if (!sta) {
|
||||
ht_dbg(sdata, "Could not find station: %pM\n", ra);
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
mutex_lock(&sta->ampdu_mlme.mtx);
|
||||
spin_lock_bh(&sta->lock);
|
||||
tid_tx = rcu_dereference_protected_tid_tx(sta, tid);
|
||||
|
||||
if (!tid_tx || !test_bit(HT_AGG_STATE_STOPPING, &tid_tx->state)) {
|
||||
if (!test_bit(HT_AGG_STATE_STOPPING, &tid_tx->state)) {
|
||||
ht_dbg(sdata,
|
||||
"unexpected callback to A-MPDU stop for %pM tid %d\n",
|
||||
sta->sta.addr, tid);
|
||||
@ -906,12 +885,8 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u8 tid)
|
||||
spin_unlock_bh(&sta->lock);
|
||||
|
||||
if (send_delba)
|
||||
ieee80211_send_delba(sdata, ra, tid,
|
||||
ieee80211_send_delba(sdata, sta->sta.addr, tid,
|
||||
WLAN_BACK_INITIATOR, WLAN_REASON_QSTA_NOT_USE);
|
||||
|
||||
mutex_unlock(&sta->ampdu_mlme.mtx);
|
||||
unlock:
|
||||
mutex_unlock(&local->sta_mtx);
|
||||
}
|
||||
|
||||
void ieee80211_stop_tx_ba_cb_irqsafe(struct ieee80211_vif *vif,
|
||||
@ -919,19 +894,20 @@ void ieee80211_stop_tx_ba_cb_irqsafe(struct ieee80211_vif *vif,
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
struct ieee80211_ra_tid *ra_tid;
|
||||
struct sk_buff *skb = dev_alloc_skb(0);
|
||||
struct sta_info *sta;
|
||||
struct tid_ampdu_tx *tid_tx;
|
||||
|
||||
if (unlikely(!skb))
|
||||
return;
|
||||
trace_api_stop_tx_ba_cb(sdata, ra, tid);
|
||||
|
||||
ra_tid = (struct ieee80211_ra_tid *) &skb->cb;
|
||||
memcpy(&ra_tid->ra, ra, ETH_ALEN);
|
||||
ra_tid->tid = tid;
|
||||
rcu_read_lock();
|
||||
tid_tx = ieee80211_lookup_tid_tx(sdata, ra, tid, &sta);
|
||||
if (!tid_tx)
|
||||
goto out;
|
||||
|
||||
skb->pkt_type = IEEE80211_SDATA_QUEUE_AGG_STOP;
|
||||
skb_queue_tail(&sdata->skb_queue, skb);
|
||||
ieee80211_queue_work(&local->hw, &sdata->work);
|
||||
set_bit(HT_AGG_STATE_STOP_CB, &tid_tx->state);
|
||||
ieee80211_queue_work(&local->hw, &sta->ampdu_mlme.work);
|
||||
out:
|
||||
rcu_read_unlock();
|
||||
}
|
||||
EXPORT_SYMBOL(ieee80211_stop_tx_ba_cb_irqsafe);
|
||||
|
||||
|
@ -7,6 +7,7 @@
|
||||
* Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
|
||||
* Copyright 2007, Michael Wu <flamingice@sourmilk.net>
|
||||
* Copyright 2007-2010, Intel Corporation
|
||||
* Copyright 2017 Intel Deutschland GmbH
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
@ -289,8 +290,6 @@ void ieee80211_sta_tear_down_BA_sessions(struct sta_info *sta,
|
||||
{
|
||||
int i;
|
||||
|
||||
cancel_work_sync(&sta->ampdu_mlme.work);
|
||||
|
||||
for (i = 0; i < IEEE80211_NUM_TIDS; i++) {
|
||||
__ieee80211_stop_tx_ba_session(sta, i, reason);
|
||||
__ieee80211_stop_rx_ba_session(sta, i, WLAN_BACK_RECIPIENT,
|
||||
@ -298,6 +297,9 @@ void ieee80211_sta_tear_down_BA_sessions(struct sta_info *sta,
|
||||
reason != AGG_STOP_DESTROY_STA &&
|
||||
reason != AGG_STOP_PEER_REQUEST);
|
||||
}
|
||||
|
||||
/* stopping might queue the work again - so cancel only afterwards */
|
||||
cancel_work_sync(&sta->ampdu_mlme.work);
|
||||
}
|
||||
|
||||
void ieee80211_ba_session_work(struct work_struct *work)
|
||||
@ -352,10 +354,16 @@ void ieee80211_ba_session_work(struct work_struct *work)
|
||||
spin_unlock_bh(&sta->lock);
|
||||
|
||||
tid_tx = rcu_dereference_protected_tid_tx(sta, tid);
|
||||
if (tid_tx && test_and_clear_bit(HT_AGG_STATE_WANT_STOP,
|
||||
&tid_tx->state))
|
||||
if (!tid_tx)
|
||||
continue;
|
||||
|
||||
if (test_and_clear_bit(HT_AGG_STATE_START_CB, &tid_tx->state))
|
||||
ieee80211_start_tx_ba_cb(sta, tid, tid_tx);
|
||||
if (test_and_clear_bit(HT_AGG_STATE_WANT_STOP, &tid_tx->state))
|
||||
___ieee80211_stop_tx_ba_session(sta, tid,
|
||||
AGG_STOP_LOCAL_REQUEST);
|
||||
if (test_and_clear_bit(HT_AGG_STATE_STOP_CB, &tid_tx->state))
|
||||
ieee80211_stop_tx_ba_cb(sta, tid, tid_tx);
|
||||
}
|
||||
mutex_unlock(&sta->ampdu_mlme.mtx);
|
||||
}
|
||||
|
@ -1036,8 +1036,6 @@ struct ieee80211_rx_agg {
|
||||
|
||||
enum sdata_queue_type {
|
||||
IEEE80211_SDATA_QUEUE_TYPE_FRAME = 0,
|
||||
IEEE80211_SDATA_QUEUE_AGG_START = 1,
|
||||
IEEE80211_SDATA_QUEUE_AGG_STOP = 2,
|
||||
IEEE80211_SDATA_QUEUE_RX_AGG_START = 3,
|
||||
IEEE80211_SDATA_QUEUE_RX_AGG_STOP = 4,
|
||||
};
|
||||
@ -1427,12 +1425,6 @@ ieee80211_get_sband(struct ieee80211_sub_if_data *sdata)
|
||||
return local->hw.wiphy->bands[band];
|
||||
}
|
||||
|
||||
/* this struct represents 802.11n's RA/TID combination */
|
||||
struct ieee80211_ra_tid {
|
||||
u8 ra[ETH_ALEN];
|
||||
u16 tid;
|
||||
};
|
||||
|
||||
/* this struct holds the value parsing from channel switch IE */
|
||||
struct ieee80211_csa_ie {
|
||||
struct cfg80211_chan_def chandef;
|
||||
@ -1794,8 +1786,10 @@ int __ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid,
|
||||
enum ieee80211_agg_stop_reason reason);
|
||||
int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid,
|
||||
enum ieee80211_agg_stop_reason reason);
|
||||
void ieee80211_start_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u16 tid);
|
||||
void ieee80211_stop_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u8 tid);
|
||||
void ieee80211_start_tx_ba_cb(struct sta_info *sta, int tid,
|
||||
struct tid_ampdu_tx *tid_tx);
|
||||
void ieee80211_stop_tx_ba_cb(struct sta_info *sta, int tid,
|
||||
struct tid_ampdu_tx *tid_tx);
|
||||
void ieee80211_ba_session_work(struct work_struct *work);
|
||||
void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid);
|
||||
void ieee80211_release_reorder_timeout(struct sta_info *sta, int tid);
|
||||
|
@ -1237,7 +1237,6 @@ static void ieee80211_iface_work(struct work_struct *work)
|
||||
struct ieee80211_local *local = sdata->local;
|
||||
struct sk_buff *skb;
|
||||
struct sta_info *sta;
|
||||
struct ieee80211_ra_tid *ra_tid;
|
||||
struct ieee80211_rx_agg *rx_agg;
|
||||
|
||||
if (!ieee80211_sdata_running(sdata))
|
||||
@ -1253,15 +1252,7 @@ static void ieee80211_iface_work(struct work_struct *work)
|
||||
while ((skb = skb_dequeue(&sdata->skb_queue))) {
|
||||
struct ieee80211_mgmt *mgmt = (void *)skb->data;
|
||||
|
||||
if (skb->pkt_type == IEEE80211_SDATA_QUEUE_AGG_START) {
|
||||
ra_tid = (void *)&skb->cb;
|
||||
ieee80211_start_tx_ba_cb(&sdata->vif, ra_tid->ra,
|
||||
ra_tid->tid);
|
||||
} else if (skb->pkt_type == IEEE80211_SDATA_QUEUE_AGG_STOP) {
|
||||
ra_tid = (void *)&skb->cb;
|
||||
ieee80211_stop_tx_ba_cb(&sdata->vif, ra_tid->ra,
|
||||
ra_tid->tid);
|
||||
} else if (skb->pkt_type == IEEE80211_SDATA_QUEUE_RX_AGG_START) {
|
||||
if (skb->pkt_type == IEEE80211_SDATA_QUEUE_RX_AGG_START) {
|
||||
rx_agg = (void *)&skb->cb;
|
||||
mutex_lock(&local->sta_mtx);
|
||||
sta = sta_info_get_bss(sdata, rx_agg->addr);
|
||||
|
@ -2155,7 +2155,7 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
|
||||
struct ieee80211_sta_rx_stats *cpurxs;
|
||||
|
||||
cpurxs = per_cpu_ptr(sta->pcpu_rx_stats, cpu);
|
||||
sinfo->rx_packets += cpurxs->dropped;
|
||||
sinfo->rx_dropped_misc += cpurxs->dropped;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -116,6 +116,8 @@ enum ieee80211_sta_info_flags {
|
||||
#define HT_AGG_STATE_STOPPING 3
|
||||
#define HT_AGG_STATE_WANT_START 4
|
||||
#define HT_AGG_STATE_WANT_STOP 5
|
||||
#define HT_AGG_STATE_START_CB 6
|
||||
#define HT_AGG_STATE_STOP_CB 7
|
||||
|
||||
enum ieee80211_agg_stop_reason {
|
||||
AGG_STOP_DECLINED,
|
||||
|
Loading…
x
Reference in New Issue
Block a user