diff options
author | Johannes Berg <johannes.berg@intel.com> | 2016-03-31 13:02:11 -0400 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2016-04-06 07:18:19 -0400 |
commit | c9c5962b56c10c34d8fedc20cd6d6ebdaa2383c6 (patch) | |
tree | 3b5b98cc8a18efeffabc86ed6ac4247b7311a294 | |
parent | 49ddf8e6e2347cffdcf83d1ca2d04ff929820178 (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.h | 4 | ||||
-rw-r--r-- | net/mac80211/debugfs.c | 1 | ||||
-rw-r--r-- | net/mac80211/rx.c | 37 | ||||
-rw-r--r-- | net/mac80211/sta_info.c | 108 | ||||
-rw-r--r-- | net/mac80211/sta_info.h | 38 |
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 | */ |
1985 | enum ieee80211_hw_flags { | 1988 | enum 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 | ||
1943 | static struct ieee80211_sta_rx_stats * | ||
1944 | sta_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 | |||
1935 | static void sta_stats_decode_rate(struct ieee80211_local *local, u16 rate, | 1965 | static 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 | ||
1968 | static void sta_set_rate_info_rx(struct sta_info *sta, struct rate_info *rinfo) | 1998 | static 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 | ||
2043 | static 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 | |||
2013 | void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) | 2056 | void 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 | ||
2214 | unsigned long ieee80211_sta_last_active(struct sta_info *sta) | 2288 | unsigned 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 | ||
368 | DECLARE_EWMA(signal, 1024, 8) | 370 | DECLARE_EWMA(signal, 1024, 8) |
369 | 371 | ||
372 | struct 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 | */ |
433 | struct sta_info { | 452 | struct 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]; |