mirror of https://gitee.com/openkylin/linux.git
mac80211: fix RX u64 stats consistency on 32-bit platforms
On 32-bit platforms, the 64-bit counters we keep need to be protected to be consistently read. Use the u64_stats_sync mechanism to do that. In order to not end up with overly long lines, refactor the tidstats assignments a bit. Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
parent
4f6b1b3daa
commit
0f9c5a61d4
|
@ -1441,7 +1441,11 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
|
|||
ieee80211_sta_rx_notify(rx->sdata, hdr);
|
||||
|
||||
sta->rx_stats.fragments++;
|
||||
|
||||
u64_stats_update_begin(&rx->sta->rx_stats.syncp);
|
||||
sta->rx_stats.bytes += rx->skb->len;
|
||||
u64_stats_update_end(&rx->sta->rx_stats.syncp);
|
||||
|
||||
if (!(status->flag & RX_FLAG_NO_SIGNAL_VAL)) {
|
||||
sta->rx_stats.last_signal = status->signal;
|
||||
ewma_signal_add(&sta->rx_stats_avg.signal, -status->signal);
|
||||
|
@ -2124,7 +2128,9 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx)
|
|||
* for non-QoS-data frames. Here we know it's a data
|
||||
* frame, so count MSDUs.
|
||||
*/
|
||||
u64_stats_update_begin(&rx->sta->rx_stats.syncp);
|
||||
rx->sta->rx_stats.msdu[rx->seqno_idx]++;
|
||||
u64_stats_update_end(&rx->sta->rx_stats.syncp);
|
||||
}
|
||||
|
||||
if ((sdata->vif.type == NL80211_IFTYPE_AP ||
|
||||
|
|
|
@ -335,6 +335,8 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
|
|||
sta->sdata = sdata;
|
||||
sta->rx_stats.last_rx = jiffies;
|
||||
|
||||
u64_stats_init(&sta->rx_stats.syncp);
|
||||
|
||||
sta->sta_state = IEEE80211_STA_NONE;
|
||||
|
||||
/* Mark TID as unreserved */
|
||||
|
@ -1971,6 +1973,41 @@ static void sta_set_rate_info_rx(struct sta_info *sta, struct rate_info *rinfo)
|
|||
sta_stats_decode_rate(sta->local, rate, rinfo);
|
||||
}
|
||||
|
||||
static void sta_set_tidstats(struct sta_info *sta,
|
||||
struct cfg80211_tid_stats *tidstats,
|
||||
int tid)
|
||||
{
|
||||
struct ieee80211_local *local = sta->local;
|
||||
|
||||
if (!(tidstats->filled & BIT(NL80211_TID_STATS_RX_MSDU))) {
|
||||
unsigned int start;
|
||||
|
||||
do {
|
||||
start = u64_stats_fetch_begin(&sta->rx_stats.syncp);
|
||||
tidstats->rx_msdu = sta->rx_stats.msdu[tid];
|
||||
} while (u64_stats_fetch_retry(&sta->rx_stats.syncp, start));
|
||||
|
||||
tidstats->filled |= BIT(NL80211_TID_STATS_RX_MSDU);
|
||||
}
|
||||
|
||||
if (!(tidstats->filled & BIT(NL80211_TID_STATS_TX_MSDU))) {
|
||||
tidstats->filled |= BIT(NL80211_TID_STATS_TX_MSDU);
|
||||
tidstats->tx_msdu = sta->tx_stats.msdu[tid];
|
||||
}
|
||||
|
||||
if (!(tidstats->filled & BIT(NL80211_TID_STATS_TX_MSDU_RETRIES)) &&
|
||||
ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS)) {
|
||||
tidstats->filled |= BIT(NL80211_TID_STATS_TX_MSDU_RETRIES);
|
||||
tidstats->tx_msdu_retries = sta->status_stats.msdu_retries[tid];
|
||||
}
|
||||
|
||||
if (!(tidstats->filled & BIT(NL80211_TID_STATS_TX_MSDU_FAILED)) &&
|
||||
ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS)) {
|
||||
tidstats->filled |= BIT(NL80211_TID_STATS_TX_MSDU_FAILED);
|
||||
tidstats->tx_msdu_failed = sta->status_stats.msdu_failed[tid];
|
||||
}
|
||||
}
|
||||
|
||||
void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata = sta->sdata;
|
||||
|
@ -2025,7 +2062,12 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
|
|||
|
||||
if (!(sinfo->filled & (BIT(NL80211_STA_INFO_RX_BYTES64) |
|
||||
BIT(NL80211_STA_INFO_RX_BYTES)))) {
|
||||
sinfo->rx_bytes = sta->rx_stats.bytes;
|
||||
unsigned int start;
|
||||
|
||||
do {
|
||||
start = u64_stats_fetch_begin(&sta->rx_stats.syncp);
|
||||
sinfo->rx_bytes = sta->rx_stats.bytes;
|
||||
} while (u64_stats_fetch_retry(&sta->rx_stats.syncp, start));
|
||||
sinfo->filled |= BIT(NL80211_STA_INFO_RX_BYTES64);
|
||||
}
|
||||
|
||||
|
@ -2097,33 +2139,7 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
|
|||
for (i = 0; i < IEEE80211_NUM_TIDS + 1; i++) {
|
||||
struct cfg80211_tid_stats *tidstats = &sinfo->pertid[i];
|
||||
|
||||
if (!(tidstats->filled & BIT(NL80211_TID_STATS_RX_MSDU))) {
|
||||
tidstats->filled |= BIT(NL80211_TID_STATS_RX_MSDU);
|
||||
tidstats->rx_msdu = sta->rx_stats.msdu[i];
|
||||
}
|
||||
|
||||
if (!(tidstats->filled & BIT(NL80211_TID_STATS_TX_MSDU))) {
|
||||
tidstats->filled |= BIT(NL80211_TID_STATS_TX_MSDU);
|
||||
tidstats->tx_msdu = sta->tx_stats.msdu[i];
|
||||
}
|
||||
|
||||
if (!(tidstats->filled &
|
||||
BIT(NL80211_TID_STATS_TX_MSDU_RETRIES)) &&
|
||||
ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS)) {
|
||||
tidstats->filled |=
|
||||
BIT(NL80211_TID_STATS_TX_MSDU_RETRIES);
|
||||
tidstats->tx_msdu_retries =
|
||||
sta->status_stats.msdu_retries[i];
|
||||
}
|
||||
|
||||
if (!(tidstats->filled &
|
||||
BIT(NL80211_TID_STATS_TX_MSDU_FAILED)) &&
|
||||
ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS)) {
|
||||
tidstats->filled |=
|
||||
BIT(NL80211_TID_STATS_TX_MSDU_FAILED);
|
||||
tidstats->tx_msdu_failed =
|
||||
sta->status_stats.msdu_failed[i];
|
||||
}
|
||||
sta_set_tidstats(sta, tidstats, i);
|
||||
}
|
||||
|
||||
if (ieee80211_vif_is_mesh(&sdata->vif)) {
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include <linux/average.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/rhashtable.h>
|
||||
#include <linux/u64_stats_sync.h>
|
||||
#include "key.h"
|
||||
|
||||
/**
|
||||
|
@ -444,7 +445,6 @@ struct sta_info {
|
|||
/* Updated from RX path only, no locking requirements */
|
||||
struct {
|
||||
unsigned long packets;
|
||||
u64 bytes;
|
||||
unsigned long last_rx;
|
||||
unsigned long num_duplicates;
|
||||
unsigned long fragments;
|
||||
|
@ -453,6 +453,9 @@ struct sta_info {
|
|||
u8 chains;
|
||||
s8 chain_signal_last[IEEE80211_MAX_CHAINS];
|
||||
u16 last_rate;
|
||||
|
||||
struct u64_stats_sync syncp;
|
||||
u64 bytes;
|
||||
u64 msdu[IEEE80211_NUM_TIDS + 1];
|
||||
} rx_stats;
|
||||
struct {
|
||||
|
|
Loading…
Reference in New Issue