aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2016-03-31 13:02:09 -0400
committerJohannes Berg <johannes.berg@intel.com>2016-04-06 07:18:17 -0400
commit0f9c5a61d4b2330b12c59126aa5a9108dbfce555 (patch)
tree6d18031607d94831c71dba87fec4abfb990c6465 /net/mac80211
parent4f6b1b3daaf167bf927174224e07efd17ed95984 (diff)
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>
Diffstat (limited to 'net/mac80211')
-rw-r--r--net/mac80211/rx.c6
-rw-r--r--net/mac80211/sta_info.c72
-rw-r--r--net/mac80211/sta_info.h5
3 files changed, 54 insertions, 29 deletions
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 5a6c36c3aed6..2863832b0db4 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -1441,7 +1441,11 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
1441 ieee80211_sta_rx_notify(rx->sdata, hdr); 1441 ieee80211_sta_rx_notify(rx->sdata, hdr);
1442 1442
1443 sta->rx_stats.fragments++; 1443 sta->rx_stats.fragments++;
1444
1445 u64_stats_update_begin(&rx->sta->rx_stats.syncp);
1444 sta->rx_stats.bytes += rx->skb->len; 1446 sta->rx_stats.bytes += rx->skb->len;
1447 u64_stats_update_end(&rx->sta->rx_stats.syncp);
1448
1445 if (!(status->flag & RX_FLAG_NO_SIGNAL_VAL)) { 1449 if (!(status->flag & RX_FLAG_NO_SIGNAL_VAL)) {
1446 sta->rx_stats.last_signal = status->signal; 1450 sta->rx_stats.last_signal = status->signal;
1447 ewma_signal_add(&sta->rx_stats_avg.signal, -status->signal); 1451 ewma_signal_add(&sta->rx_stats_avg.signal, -status->signal);
@@ -2124,7 +2128,9 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx)
2124 * for non-QoS-data frames. Here we know it's a data 2128 * for non-QoS-data frames. Here we know it's a data
2125 * frame, so count MSDUs. 2129 * frame, so count MSDUs.
2126 */ 2130 */
2131 u64_stats_update_begin(&rx->sta->rx_stats.syncp);
2127 rx->sta->rx_stats.msdu[rx->seqno_idx]++; 2132 rx->sta->rx_stats.msdu[rx->seqno_idx]++;
2133 u64_stats_update_end(&rx->sta->rx_stats.syncp);
2128 } 2134 }
2129 2135
2130 if ((sdata->vif.type == NL80211_IFTYPE_AP || 2136 if ((sdata->vif.type == NL80211_IFTYPE_AP ||
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index 0b50ae3f0b05..bdd303e8b577 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -335,6 +335,8 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
335 sta->sdata = sdata; 335 sta->sdata = sdata;
336 sta->rx_stats.last_rx = jiffies; 336 sta->rx_stats.last_rx = jiffies;
337 337
338 u64_stats_init(&sta->rx_stats.syncp);
339
338 sta->sta_state = IEEE80211_STA_NONE; 340 sta->sta_state = IEEE80211_STA_NONE;
339 341
340 /* Mark TID as unreserved */ 342 /* Mark TID as unreserved */
@@ -1971,6 +1973,41 @@ static void sta_set_rate_info_rx(struct sta_info *sta, struct rate_info *rinfo)
1971 sta_stats_decode_rate(sta->local, rate, rinfo); 1973 sta_stats_decode_rate(sta->local, rate, rinfo);
1972} 1974}
1973 1975
1976static void sta_set_tidstats(struct sta_info *sta,
1977 struct cfg80211_tid_stats *tidstats,
1978 int tid)
1979{
1980 struct ieee80211_local *local = sta->local;
1981
1982 if (!(tidstats->filled & BIT(NL80211_TID_STATS_RX_MSDU))) {
1983 unsigned int start;
1984
1985 do {
1986 start = u64_stats_fetch_begin(&sta->rx_stats.syncp);
1987 tidstats->rx_msdu = sta->rx_stats.msdu[tid];
1988 } while (u64_stats_fetch_retry(&sta->rx_stats.syncp, start));
1989
1990 tidstats->filled |= BIT(NL80211_TID_STATS_RX_MSDU);
1991 }
1992
1993 if (!(tidstats->filled & BIT(NL80211_TID_STATS_TX_MSDU))) {
1994 tidstats->filled |= BIT(NL80211_TID_STATS_TX_MSDU);
1995 tidstats->tx_msdu = sta->tx_stats.msdu[tid];
1996 }
1997
1998 if (!(tidstats->filled & BIT(NL80211_TID_STATS_TX_MSDU_RETRIES)) &&
1999 ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS)) {
2000 tidstats->filled |= BIT(NL80211_TID_STATS_TX_MSDU_RETRIES);
2001 tidstats->tx_msdu_retries = sta->status_stats.msdu_retries[tid];
2002 }
2003
2004 if (!(tidstats->filled & BIT(NL80211_TID_STATS_TX_MSDU_FAILED)) &&
2005 ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS)) {
2006 tidstats->filled |= BIT(NL80211_TID_STATS_TX_MSDU_FAILED);
2007 tidstats->tx_msdu_failed = sta->status_stats.msdu_failed[tid];
2008 }
2009}
2010
1974void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) 2011void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
1975{ 2012{
1976 struct ieee80211_sub_if_data *sdata = sta->sdata; 2013 struct ieee80211_sub_if_data *sdata = sta->sdata;
@@ -2025,7 +2062,12 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
2025 2062
2026 if (!(sinfo->filled & (BIT(NL80211_STA_INFO_RX_BYTES64) | 2063 if (!(sinfo->filled & (BIT(NL80211_STA_INFO_RX_BYTES64) |
2027 BIT(NL80211_STA_INFO_RX_BYTES)))) { 2064 BIT(NL80211_STA_INFO_RX_BYTES)))) {
2028 sinfo->rx_bytes = sta->rx_stats.bytes; 2065 unsigned int start;
2066
2067 do {
2068 start = u64_stats_fetch_begin(&sta->rx_stats.syncp);
2069 sinfo->rx_bytes = sta->rx_stats.bytes;
2070 } while (u64_stats_fetch_retry(&sta->rx_stats.syncp, start));
2029 sinfo->filled |= BIT(NL80211_STA_INFO_RX_BYTES64); 2071 sinfo->filled |= BIT(NL80211_STA_INFO_RX_BYTES64);
2030 } 2072 }
2031 2073
@@ -2097,33 +2139,7 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
2097 for (i = 0; i < IEEE80211_NUM_TIDS + 1; i++) { 2139 for (i = 0; i < IEEE80211_NUM_TIDS + 1; i++) {
2098 struct cfg80211_tid_stats *tidstats = &sinfo->pertid[i]; 2140 struct cfg80211_tid_stats *tidstats = &sinfo->pertid[i];
2099 2141
2100 if (!(tidstats->filled & BIT(NL80211_TID_STATS_RX_MSDU))) { 2142 sta_set_tidstats(sta, tidstats, i);
2101 tidstats->filled |= BIT(NL80211_TID_STATS_RX_MSDU);
2102 tidstats->rx_msdu = sta->rx_stats.msdu[i];
2103 }
2104
2105 if (!(tidstats->filled & BIT(NL80211_TID_STATS_TX_MSDU))) {
2106 tidstats->filled |= BIT(NL80211_TID_STATS_TX_MSDU);
2107 tidstats->tx_msdu = sta->tx_stats.msdu[i];
2108 }
2109
2110 if (!(tidstats->filled &
2111 BIT(NL80211_TID_STATS_TX_MSDU_RETRIES)) &&
2112 ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS)) {
2113 tidstats->filled |=
2114 BIT(NL80211_TID_STATS_TX_MSDU_RETRIES);
2115 tidstats->tx_msdu_retries =
2116 sta->status_stats.msdu_retries[i];
2117 }
2118
2119 if (!(tidstats->filled &
2120 BIT(NL80211_TID_STATS_TX_MSDU_FAILED)) &&
2121 ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS)) {
2122 tidstats->filled |=
2123 BIT(NL80211_TID_STATS_TX_MSDU_FAILED);
2124 tidstats->tx_msdu_failed =
2125 sta->status_stats.msdu_failed[i];
2126 }
2127 } 2143 }
2128 2144
2129 if (ieee80211_vif_is_mesh(&sdata->vif)) { 2145 if (ieee80211_vif_is_mesh(&sdata->vif)) {
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index 5549ceb9cbb3..7c23b575672e 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -18,6 +18,7 @@
18#include <linux/average.h> 18#include <linux/average.h>
19#include <linux/etherdevice.h> 19#include <linux/etherdevice.h>
20#include <linux/rhashtable.h> 20#include <linux/rhashtable.h>
21#include <linux/u64_stats_sync.h>
21#include "key.h" 22#include "key.h"
22 23
23/** 24/**
@@ -444,7 +445,6 @@ struct sta_info {
444 /* Updated from RX path only, no locking requirements */ 445 /* Updated from RX path only, no locking requirements */
445 struct { 446 struct {
446 unsigned long packets; 447 unsigned long packets;
447 u64 bytes;
448 unsigned long last_rx; 448 unsigned long last_rx;
449 unsigned long num_duplicates; 449 unsigned long num_duplicates;
450 unsigned long fragments; 450 unsigned long fragments;
@@ -453,6 +453,9 @@ struct sta_info {
453 u8 chains; 453 u8 chains;
454 s8 chain_signal_last[IEEE80211_MAX_CHAINS]; 454 s8 chain_signal_last[IEEE80211_MAX_CHAINS];
455 u16 last_rate; 455 u16 last_rate;
456
457 struct u64_stats_sync syncp;
458 u64 bytes;
456 u64 msdu[IEEE80211_NUM_TIDS + 1]; 459 u64 msdu[IEEE80211_NUM_TIDS + 1];
457 } rx_stats; 460 } rx_stats;
458 struct { 461 struct {