aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2016-03-31 13:02:11 -0400
committerJohannes Berg <johannes.berg@intel.com>2016-04-06 07:18:19 -0400
commitc9c5962b56c10c34d8fedc20cd6d6ebdaa2383c6 (patch)
tree3b5b98cc8a18efeffabc86ed6ac4247b7311a294
parent49ddf8e6e2347cffdcf83d1ca2d04ff929820178 (diff)
mac80211: enable collecting station statistics per-CPU
If the driver advertises the new HW flag USE_RSS, make the station statistics on the fast-rx path per-CPU. This will enable calling the RX in parallel, only hitting locking or shared cachelines when the fast-RX path isn't available. Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-rw-r--r--include/net/mac80211.h4
-rw-r--r--net/mac80211/debugfs.c1
-rw-r--r--net/mac80211/rx.c37
-rw-r--r--net/mac80211/sta_info.c108
-rw-r--r--net/mac80211/sta_info.h38
5 files changed, 142 insertions, 46 deletions
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index fd5ec446a7a9..5f4b4c773a92 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -1980,6 +1980,9 @@ struct ieee80211_txq {
1980 * order and does not need to manage its own reorder buffer or BA session 1980 * order and does not need to manage its own reorder buffer or BA session
1981 * timeout. 1981 * timeout.
1982 * 1982 *
1983 * @IEEE80211_HW_USES_RSS: The device uses RSS and thus requires parallel RX,
1984 * which implies using per-CPU station statistics.
1985 *
1983 * @NUM_IEEE80211_HW_FLAGS: number of hardware flags, used for sizing arrays 1986 * @NUM_IEEE80211_HW_FLAGS: number of hardware flags, used for sizing arrays
1984 */ 1987 */
1985enum ieee80211_hw_flags { 1988enum ieee80211_hw_flags {
@@ -2017,6 +2020,7 @@ enum ieee80211_hw_flags {
2017 IEEE80211_HW_BEACON_TX_STATUS, 2020 IEEE80211_HW_BEACON_TX_STATUS,
2018 IEEE80211_HW_NEEDS_UNIQUE_STA_ADDR, 2021 IEEE80211_HW_NEEDS_UNIQUE_STA_ADDR,
2019 IEEE80211_HW_SUPPORTS_REORDERING_BUFFER, 2022 IEEE80211_HW_SUPPORTS_REORDERING_BUFFER,
2023 IEEE80211_HW_USES_RSS,
2020 2024
2021 /* keep last, obviously */ 2025 /* keep last, obviously */
2022 NUM_IEEE80211_HW_FLAGS 2026 NUM_IEEE80211_HW_FLAGS
diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c
index 4ab5c522ceee..52ed2afc408d 100644
--- a/net/mac80211/debugfs.c
+++ b/net/mac80211/debugfs.c
@@ -127,6 +127,7 @@ static const char *hw_flag_names[] = {
127 FLAG(BEACON_TX_STATUS), 127 FLAG(BEACON_TX_STATUS),
128 FLAG(NEEDS_UNIQUE_STA_ADDR), 128 FLAG(NEEDS_UNIQUE_STA_ADDR),
129 FLAG(SUPPORTS_REORDERING_BUFFER), 129 FLAG(SUPPORTS_REORDERING_BUFFER),
130 FLAG(USES_RSS),
130#undef FLAG 131#undef FLAG
131}; 132};
132 133
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 96f8bbf21649..c2b659e9a9f9 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -3528,6 +3528,8 @@ void ieee80211_check_fast_rx(struct sta_info *sta)
3528 ether_addr_copy(fastrx.rfc1042_hdr, rfc1042_header); 3528 ether_addr_copy(fastrx.rfc1042_hdr, rfc1042_header);
3529 ether_addr_copy(fastrx.vif_addr, sdata->vif.addr); 3529 ether_addr_copy(fastrx.vif_addr, sdata->vif.addr);
3530 3530
3531 fastrx.uses_rss = ieee80211_hw_check(&local->hw, USES_RSS);
3532
3531 /* fast-rx doesn't do reordering */ 3533 /* fast-rx doesn't do reordering */
3532 if (ieee80211_hw_check(&local->hw, AMPDU_AGGREGATION) && 3534 if (ieee80211_hw_check(&local->hw, AMPDU_AGGREGATION) &&
3533 !ieee80211_hw_check(&local->hw, SUPPORTS_REORDERING_BUFFER)) 3535 !ieee80211_hw_check(&local->hw, SUPPORTS_REORDERING_BUFFER))
@@ -3678,6 +3680,10 @@ static bool ieee80211_invoke_fast_rx(struct ieee80211_rx_data *rx,
3678 u8 da[ETH_ALEN]; 3680 u8 da[ETH_ALEN];
3679 u8 sa[ETH_ALEN]; 3681 u8 sa[ETH_ALEN];
3680 } addrs __aligned(2); 3682 } addrs __aligned(2);
3683 struct ieee80211_sta_rx_stats *stats = &sta->rx_stats;
3684
3685 if (fast_rx->uses_rss)
3686 stats = this_cpu_ptr(sta->pcpu_rx_stats);
3681 3687
3682 /* for parallel-rx, we need to have DUP_VALIDATED, otherwise we write 3688 /* for parallel-rx, we need to have DUP_VALIDATED, otherwise we write
3683 * to a common data structure; drivers can implement that per queue 3689 * to a common data structure; drivers can implement that per queue
@@ -3759,29 +3765,32 @@ static bool ieee80211_invoke_fast_rx(struct ieee80211_rx_data *rx,
3759 } 3765 }
3760 3766
3761 /* statistics part of ieee80211_rx_h_sta_process() */ 3767 /* statistics part of ieee80211_rx_h_sta_process() */
3762 sta->rx_stats.last_rx = jiffies; 3768 stats->last_rx = jiffies;
3763 sta->rx_stats.last_rate = sta_stats_encode_rate(status); 3769 stats->last_rate = sta_stats_encode_rate(status);
3764 3770
3765 sta->rx_stats.fragments++; 3771 stats->fragments++;
3766 3772
3767 if (!(status->flag & RX_FLAG_NO_SIGNAL_VAL)) { 3773 if (!(status->flag & RX_FLAG_NO_SIGNAL_VAL)) {
3768 sta->rx_stats.last_signal = status->signal; 3774 stats->last_signal = status->signal;
3769 ewma_signal_add(&sta->rx_stats_avg.signal, -status->signal); 3775 if (!fast_rx->uses_rss)
3776 ewma_signal_add(&sta->rx_stats_avg.signal,
3777 -status->signal);
3770 } 3778 }
3771 3779
3772 if (status->chains) { 3780 if (status->chains) {
3773 int i; 3781 int i;
3774 3782
3775 sta->rx_stats.chains = status->chains; 3783 stats->chains = status->chains;
3776 for (i = 0; i < ARRAY_SIZE(status->chain_signal); i++) { 3784 for (i = 0; i < ARRAY_SIZE(status->chain_signal); i++) {
3777 int signal = status->chain_signal[i]; 3785 int signal = status->chain_signal[i];
3778 3786
3779 if (!(status->chains & BIT(i))) 3787 if (!(status->chains & BIT(i)))
3780 continue; 3788 continue;
3781 3789
3782 sta->rx_stats.chain_signal_last[i] = signal; 3790 stats->chain_signal_last[i] = signal;
3783 ewma_signal_add(&sta->rx_stats_avg.chain_signal[i], 3791 if (!fast_rx->uses_rss)
3784 -signal); 3792 ewma_signal_add(&sta->rx_stats_avg.chain_signal[i],
3793 -signal);
3785 } 3794 }
3786 } 3795 }
3787 /* end of statistics */ 3796 /* end of statistics */
@@ -3806,10 +3815,10 @@ static bool ieee80211_invoke_fast_rx(struct ieee80211_rx_data *rx,
3806 * for non-QoS-data frames. Here we know it's a data 3815 * for non-QoS-data frames. Here we know it's a data
3807 * frame, so count MSDUs. 3816 * frame, so count MSDUs.
3808 */ 3817 */
3809 u64_stats_update_begin(&sta->rx_stats.syncp); 3818 u64_stats_update_begin(&stats->syncp);
3810 sta->rx_stats.msdu[rx->seqno_idx]++; 3819 stats->msdu[rx->seqno_idx]++;
3811 sta->rx_stats.bytes += orig_len; 3820 stats->bytes += orig_len;
3812 u64_stats_update_end(&sta->rx_stats.syncp); 3821 u64_stats_update_end(&stats->syncp);
3813 3822
3814 if (fast_rx->internal_forward) { 3823 if (fast_rx->internal_forward) {
3815 struct sta_info *dsta = sta_info_get(rx->sdata, skb->data); 3824 struct sta_info *dsta = sta_info_get(rx->sdata, skb->data);
@@ -3840,7 +3849,7 @@ static bool ieee80211_invoke_fast_rx(struct ieee80211_rx_data *rx,
3840 return true; 3849 return true;
3841 drop: 3850 drop:
3842 dev_kfree_skb(skb); 3851 dev_kfree_skb(skb);
3843 sta->rx_stats.dropped++; 3852 stats->dropped++;
3844 return true; 3853 return true;
3845} 3854}
3846 3855
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index a0ce7e40f420..cf2aca0cc200 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -254,6 +254,7 @@ void sta_info_free(struct ieee80211_local *local, struct sta_info *sta)
254#ifdef CONFIG_MAC80211_MESH 254#ifdef CONFIG_MAC80211_MESH
255 kfree(sta->mesh); 255 kfree(sta->mesh);
256#endif 256#endif
257 free_percpu(sta->pcpu_rx_stats);
257 kfree(sta); 258 kfree(sta);
258} 259}
259 260
@@ -311,6 +312,13 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata,
311 if (!sta) 312 if (!sta)
312 return NULL; 313 return NULL;
313 314
315 if (ieee80211_hw_check(hw, USES_RSS)) {
316 sta->pcpu_rx_stats =
317 alloc_percpu(struct ieee80211_sta_rx_stats);
318 if (!sta->pcpu_rx_stats)
319 goto free;
320 }
321
314 spin_lock_init(&sta->lock); 322 spin_lock_init(&sta->lock);
315 spin_lock_init(&sta->ps_lock); 323 spin_lock_init(&sta->ps_lock);
316 INIT_WORK(&sta->drv_deliver_wk, sta_deliver_ps_frames); 324 INIT_WORK(&sta->drv_deliver_wk, sta_deliver_ps_frames);
@@ -1932,6 +1940,28 @@ u8 sta_info_tx_streams(struct sta_info *sta)
1932 >> IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT) + 1; 1940 >> IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT) + 1;
1933} 1941}
1934 1942
1943static struct ieee80211_sta_rx_stats *
1944sta_get_last_rx_stats(struct sta_info *sta)
1945{
1946 struct ieee80211_sta_rx_stats *stats = &sta->rx_stats;
1947 struct ieee80211_local *local = sta->local;
1948 int cpu;
1949
1950 if (!ieee80211_hw_check(&local->hw, USES_RSS))
1951 return stats;
1952
1953 for_each_possible_cpu(cpu) {
1954 struct ieee80211_sta_rx_stats *cpustats;
1955
1956 cpustats = per_cpu_ptr(sta->pcpu_rx_stats, cpu);
1957
1958 if (time_after(cpustats->last_rx, stats->last_rx))
1959 stats = cpustats;
1960 }
1961
1962 return stats;
1963}
1964
1935static void sta_stats_decode_rate(struct ieee80211_local *local, u16 rate, 1965static void sta_stats_decode_rate(struct ieee80211_local *local, u16 rate,
1936 struct rate_info *rinfo) 1966 struct rate_info *rinfo)
1937{ 1967{
@@ -1967,7 +1997,7 @@ static void sta_stats_decode_rate(struct ieee80211_local *local, u16 rate,
1967 1997
1968static void sta_set_rate_info_rx(struct sta_info *sta, struct rate_info *rinfo) 1998static void sta_set_rate_info_rx(struct sta_info *sta, struct rate_info *rinfo)
1969{ 1999{
1970 u16 rate = ACCESS_ONCE(sta->rx_stats.last_rate); 2000 u16 rate = ACCESS_ONCE(sta_get_last_rx_stats(sta)->last_rate);
1971 2001
1972 if (rate == STA_STATS_RATE_INVALID) 2002 if (rate == STA_STATS_RATE_INVALID)
1973 rinfo->flags = 0; 2003 rinfo->flags = 0;
@@ -2010,13 +2040,29 @@ static void sta_set_tidstats(struct sta_info *sta,
2010 } 2040 }
2011} 2041}
2012 2042
2043static inline u64 sta_get_stats_bytes(struct ieee80211_sta_rx_stats *rxstats)
2044{
2045 unsigned int start;
2046 u64 value;
2047
2048 do {
2049 start = u64_stats_fetch_begin(&rxstats->syncp);
2050 value = rxstats->bytes;
2051 } while (u64_stats_fetch_retry(&rxstats->syncp, start));
2052
2053 return value;
2054}
2055
2013void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) 2056void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
2014{ 2057{
2015 struct ieee80211_sub_if_data *sdata = sta->sdata; 2058 struct ieee80211_sub_if_data *sdata = sta->sdata;
2016 struct ieee80211_local *local = sdata->local; 2059 struct ieee80211_local *local = sdata->local;
2017 struct rate_control_ref *ref = NULL; 2060 struct rate_control_ref *ref = NULL;
2018 u32 thr = 0; 2061 u32 thr = 0;
2019 int i, ac; 2062 int i, ac, cpu;
2063 struct ieee80211_sta_rx_stats *last_rxstats;
2064
2065 last_rxstats = sta_get_last_rx_stats(sta);
2020 2066
2021 if (test_sta_flag(sta, WLAN_STA_RATE_CONTROL)) 2067 if (test_sta_flag(sta, WLAN_STA_RATE_CONTROL))
2022 ref = local->rate_ctrl; 2068 ref = local->rate_ctrl;
@@ -2064,17 +2110,30 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
2064 2110
2065 if (!(sinfo->filled & (BIT(NL80211_STA_INFO_RX_BYTES64) | 2111 if (!(sinfo->filled & (BIT(NL80211_STA_INFO_RX_BYTES64) |
2066 BIT(NL80211_STA_INFO_RX_BYTES)))) { 2112 BIT(NL80211_STA_INFO_RX_BYTES)))) {
2067 unsigned int start; 2113 sinfo->rx_bytes += sta_get_stats_bytes(&sta->rx_stats);
2114
2115 if (sta->pcpu_rx_stats) {
2116 for_each_possible_cpu(cpu) {
2117 struct ieee80211_sta_rx_stats *cpurxs;
2118
2119 cpurxs = per_cpu_ptr(sta->pcpu_rx_stats, cpu);
2120 sinfo->rx_bytes += sta_get_stats_bytes(cpurxs);
2121 }
2122 }
2068 2123
2069 do {
2070 start = u64_stats_fetch_begin(&sta->rx_stats.syncp);
2071 sinfo->rx_bytes = sta->rx_stats.bytes;
2072 } while (u64_stats_fetch_retry(&sta->rx_stats.syncp, start));
2073 sinfo->filled |= BIT(NL80211_STA_INFO_RX_BYTES64); 2124 sinfo->filled |= BIT(NL80211_STA_INFO_RX_BYTES64);
2074 } 2125 }
2075 2126
2076 if (!(sinfo->filled & BIT(NL80211_STA_INFO_RX_PACKETS))) { 2127 if (!(sinfo->filled & BIT(NL80211_STA_INFO_RX_PACKETS))) {
2077 sinfo->rx_packets = sta->rx_stats.packets; 2128 sinfo->rx_packets = sta->rx_stats.packets;
2129 if (sta->pcpu_rx_stats) {
2130 for_each_possible_cpu(cpu) {
2131 struct ieee80211_sta_rx_stats *cpurxs;
2132
2133 cpurxs = per_cpu_ptr(sta->pcpu_rx_stats, cpu);
2134 sinfo->rx_packets += cpurxs->packets;
2135 }
2136 }
2078 sinfo->filled |= BIT(NL80211_STA_INFO_RX_PACKETS); 2137 sinfo->filled |= BIT(NL80211_STA_INFO_RX_PACKETS);
2079 } 2138 }
2080 2139
@@ -2089,6 +2148,14 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
2089 } 2148 }
2090 2149
2091 sinfo->rx_dropped_misc = sta->rx_stats.dropped; 2150 sinfo->rx_dropped_misc = sta->rx_stats.dropped;
2151 if (sta->pcpu_rx_stats) {
2152 for_each_possible_cpu(cpu) {
2153 struct ieee80211_sta_rx_stats *cpurxs;
2154
2155 cpurxs = per_cpu_ptr(sta->pcpu_rx_stats, cpu);
2156 sinfo->rx_packets += cpurxs->dropped;
2157 }
2158 }
2092 2159
2093 if (sdata->vif.type == NL80211_IFTYPE_STATION && 2160 if (sdata->vif.type == NL80211_IFTYPE_STATION &&
2094 !(sdata->vif.driver_flags & IEEE80211_VIF_BEACON_FILTER)) { 2161 !(sdata->vif.driver_flags & IEEE80211_VIF_BEACON_FILTER)) {
@@ -2100,27 +2167,34 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
2100 if (ieee80211_hw_check(&sta->local->hw, SIGNAL_DBM) || 2167 if (ieee80211_hw_check(&sta->local->hw, SIGNAL_DBM) ||
2101 ieee80211_hw_check(&sta->local->hw, SIGNAL_UNSPEC)) { 2168 ieee80211_hw_check(&sta->local->hw, SIGNAL_UNSPEC)) {
2102 if (!(sinfo->filled & BIT(NL80211_STA_INFO_SIGNAL))) { 2169 if (!(sinfo->filled & BIT(NL80211_STA_INFO_SIGNAL))) {
2103 sinfo->signal = (s8)sta->rx_stats.last_signal; 2170 sinfo->signal = (s8)last_rxstats->last_signal;
2104 sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL); 2171 sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL);
2105 } 2172 }
2106 2173
2107 if (!(sinfo->filled & BIT(NL80211_STA_INFO_SIGNAL_AVG))) { 2174 if (!sta->pcpu_rx_stats &&
2175 !(sinfo->filled & BIT(NL80211_STA_INFO_SIGNAL_AVG))) {
2108 sinfo->signal_avg = 2176 sinfo->signal_avg =
2109 -ewma_signal_read(&sta->rx_stats_avg.signal); 2177 -ewma_signal_read(&sta->rx_stats_avg.signal);
2110 sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL_AVG); 2178 sinfo->filled |= BIT(NL80211_STA_INFO_SIGNAL_AVG);
2111 } 2179 }
2112 } 2180 }
2113 2181
2114 if (sta->rx_stats.chains && 2182 /* for the average - if pcpu_rx_stats isn't set - rxstats must point to
2183 * the sta->rx_stats struct, so the check here is fine with and without
2184 * pcpu statistics
2185 */
2186 if (last_rxstats->chains &&
2115 !(sinfo->filled & (BIT(NL80211_STA_INFO_CHAIN_SIGNAL) | 2187 !(sinfo->filled & (BIT(NL80211_STA_INFO_CHAIN_SIGNAL) |
2116 BIT(NL80211_STA_INFO_CHAIN_SIGNAL_AVG)))) { 2188 BIT(NL80211_STA_INFO_CHAIN_SIGNAL_AVG)))) {
2117 sinfo->filled |= BIT(NL80211_STA_INFO_CHAIN_SIGNAL) | 2189 sinfo->filled |= BIT(NL80211_STA_INFO_CHAIN_SIGNAL);
2118 BIT(NL80211_STA_INFO_CHAIN_SIGNAL_AVG); 2190 if (!sta->pcpu_rx_stats)
2191 sinfo->filled |= BIT(NL80211_STA_INFO_CHAIN_SIGNAL_AVG);
2192
2193 sinfo->chains = last_rxstats->chains;
2119 2194
2120 sinfo->chains = sta->rx_stats.chains;
2121 for (i = 0; i < ARRAY_SIZE(sinfo->chain_signal); i++) { 2195 for (i = 0; i < ARRAY_SIZE(sinfo->chain_signal); i++) {
2122 sinfo->chain_signal[i] = 2196 sinfo->chain_signal[i] =
2123 sta->rx_stats.chain_signal_last[i]; 2197 last_rxstats->chain_signal_last[i];
2124 sinfo->chain_signal_avg[i] = 2198 sinfo->chain_signal_avg[i] =
2125 -ewma_signal_read(&sta->rx_stats_avg.chain_signal[i]); 2199 -ewma_signal_read(&sta->rx_stats_avg.chain_signal[i]);
2126 } 2200 }
@@ -2213,7 +2287,9 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
2213 2287
2214unsigned long ieee80211_sta_last_active(struct sta_info *sta) 2288unsigned long ieee80211_sta_last_active(struct sta_info *sta)
2215{ 2289{
2216 if (time_after(sta->rx_stats.last_rx, sta->status_stats.last_ack)) 2290 struct ieee80211_sta_rx_stats *stats = sta_get_last_rx_stats(sta);
2217 return sta->rx_stats.last_rx; 2291
2292 if (time_after(stats->last_rx, sta->status_stats.last_ack))
2293 return stats->last_rx;
2218 return sta->status_stats.last_ack; 2294 return sta->status_stats.last_ack;
2219} 2295}
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index a0a06609338d..dd6c6d400208 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -297,6 +297,7 @@ struct ieee80211_fast_tx {
297 * @key: bool indicating encryption is expected (key is set) 297 * @key: bool indicating encryption is expected (key is set)
298 * @sta_notify: notify the MLME code (once) 298 * @sta_notify: notify the MLME code (once)
299 * @internal_forward: forward froms internally on AP/VLAN type interfaces 299 * @internal_forward: forward froms internally on AP/VLAN type interfaces
300 * @uses_rss: copy of USES_RSS hw flag
300 * @da_offs: offset of the DA in the header (for header conversion) 301 * @da_offs: offset of the DA in the header (for header conversion)
301 * @sa_offs: offset of the SA in the header (for header conversion) 302 * @sa_offs: offset of the SA in the header (for header conversion)
302 * @rcu_head: RCU head for freeing this structure 303 * @rcu_head: RCU head for freeing this structure
@@ -311,7 +312,8 @@ struct ieee80211_fast_rx {
311 u8 icv_len; 312 u8 icv_len;
312 u8 key:1, 313 u8 key:1,
313 sta_notify:1, 314 sta_notify:1,
314 internal_forward:1; 315 internal_forward:1,
316 uses_rss:1;
315 u8 da_offs, sa_offs; 317 u8 da_offs, sa_offs;
316 318
317 struct rcu_head rcu_head; 319 struct rcu_head rcu_head;
@@ -367,6 +369,21 @@ struct mesh_sta {
367 369
368DECLARE_EWMA(signal, 1024, 8) 370DECLARE_EWMA(signal, 1024, 8)
369 371
372struct ieee80211_sta_rx_stats {
373 unsigned long packets;
374 unsigned long last_rx;
375 unsigned long num_duplicates;
376 unsigned long fragments;
377 unsigned long dropped;
378 int last_signal;
379 u8 chains;
380 s8 chain_signal_last[IEEE80211_MAX_CHAINS];
381 u16 last_rate;
382 struct u64_stats_sync syncp;
383 u64 bytes;
384 u64 msdu[IEEE80211_NUM_TIDS + 1];
385};
386
370/** 387/**
371 * struct sta_info - STA information 388 * struct sta_info - STA information
372 * 389 *
@@ -428,6 +445,8 @@ DECLARE_EWMA(signal, 1024, 8)
428 * the BSS one. 445 * the BSS one.
429 * @tx_stats: TX statistics 446 * @tx_stats: TX statistics
430 * @rx_stats: RX statistics 447 * @rx_stats: RX statistics
448 * @pcpu_rx_stats: per-CPU RX statistics, assigned only if the driver needs
449 * this (by advertising the USES_RSS hw flag)
431 * @status_stats: TX status statistics 450 * @status_stats: TX status statistics
432 */ 451 */
433struct sta_info { 452struct sta_info {
@@ -448,6 +467,7 @@ struct sta_info {
448 467
449 struct ieee80211_fast_tx __rcu *fast_tx; 468 struct ieee80211_fast_tx __rcu *fast_tx;
450 struct ieee80211_fast_rx __rcu *fast_rx; 469 struct ieee80211_fast_rx __rcu *fast_rx;
470 struct ieee80211_sta_rx_stats __percpu *pcpu_rx_stats;
451 471
452#ifdef CONFIG_MAC80211_MESH 472#ifdef CONFIG_MAC80211_MESH
453 struct mesh_sta *mesh; 473 struct mesh_sta *mesh;
@@ -477,21 +497,7 @@ struct sta_info {
477 long last_connected; 497 long last_connected;
478 498
479 /* Updated from RX path only, no locking requirements */ 499 /* Updated from RX path only, no locking requirements */
480 struct { 500 struct ieee80211_sta_rx_stats rx_stats;
481 unsigned long packets;
482 unsigned long last_rx;
483 unsigned long num_duplicates;
484 unsigned long fragments;
485 unsigned long dropped;
486 int last_signal;
487 u8 chains;
488 s8 chain_signal_last[IEEE80211_MAX_CHAINS];
489 u16 last_rate;
490
491 struct u64_stats_sync syncp;
492 u64 bytes;
493 u64 msdu[IEEE80211_NUM_TIDS + 1];
494 } rx_stats;
495 struct { 501 struct {
496 struct ewma_signal signal; 502 struct ewma_signal signal;
497 struct ewma_signal chain_signal[IEEE80211_MAX_CHAINS]; 503 struct ewma_signal chain_signal[IEEE80211_MAX_CHAINS];