aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/cfg.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2013-02-05 04:55:21 -0500
committerJohannes Berg <johannes.berg@intel.com>2013-03-07 08:32:18 -0500
commit560d268220d3416a2d473bcc906ea2ccbf51e4ec (patch)
tree4cc83a5346d70fc14ec1874d9ad5c9714b64a0a0 /net/mac80211/cfg.c
parent87f59c70ce6d1abeaaf97594835be29f746b81a0 (diff)
mac80211: provide race-free 64-bit traffic counters
Make the TX bytes/packets counters race-free by keeping them per AC so concurrent TX on queues can't cause lost or wrong updates. This works since each station belongs to a single interface. While at it also make the bytes counters 64-bit. Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/mac80211/cfg.c')
-rw-r--r--net/mac80211/cfg.c23
1 files changed, 15 insertions, 8 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 1d1ddabd89ca..61fc9116380d 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -445,12 +445,14 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
445 struct ieee80211_sub_if_data *sdata = sta->sdata; 445 struct ieee80211_sub_if_data *sdata = sta->sdata;
446 struct ieee80211_local *local = sdata->local; 446 struct ieee80211_local *local = sdata->local;
447 struct timespec uptime; 447 struct timespec uptime;
448 u64 packets = 0;
449 int ac;
448 450
449 sinfo->generation = sdata->local->sta_generation; 451 sinfo->generation = sdata->local->sta_generation;
450 452
451 sinfo->filled = STATION_INFO_INACTIVE_TIME | 453 sinfo->filled = STATION_INFO_INACTIVE_TIME |
452 STATION_INFO_RX_BYTES | 454 STATION_INFO_RX_BYTES64 |
453 STATION_INFO_TX_BYTES | 455 STATION_INFO_TX_BYTES64 |
454 STATION_INFO_RX_PACKETS | 456 STATION_INFO_RX_PACKETS |
455 STATION_INFO_TX_PACKETS | 457 STATION_INFO_TX_PACKETS |
456 STATION_INFO_TX_RETRIES | 458 STATION_INFO_TX_RETRIES |
@@ -467,10 +469,14 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
467 sinfo->connected_time = uptime.tv_sec - sta->last_connected; 469 sinfo->connected_time = uptime.tv_sec - sta->last_connected;
468 470
469 sinfo->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx); 471 sinfo->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx);
472 sinfo->tx_bytes = 0;
473 for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
474 sinfo->tx_bytes += sta->tx_bytes[ac];
475 packets += sta->tx_packets[ac];
476 }
477 sinfo->tx_packets = packets;
470 sinfo->rx_bytes = sta->rx_bytes; 478 sinfo->rx_bytes = sta->rx_bytes;
471 sinfo->tx_bytes = sta->tx_bytes;
472 sinfo->rx_packets = sta->rx_packets; 479 sinfo->rx_packets = sta->rx_packets;
473 sinfo->tx_packets = sta->tx_packets;
474 sinfo->tx_retries = sta->tx_retry_count; 480 sinfo->tx_retries = sta->tx_retry_count;
475 sinfo->tx_failed = sta->tx_retry_failed; 481 sinfo->tx_failed = sta->tx_retry_failed;
476 sinfo->rx_dropped_misc = sta->rx_dropped; 482 sinfo->rx_dropped_misc = sta->rx_dropped;
@@ -598,8 +604,8 @@ static void ieee80211_get_et_stats(struct wiphy *wiphy,
598 data[i++] += sta->rx_fragments; \ 604 data[i++] += sta->rx_fragments; \
599 data[i++] += sta->rx_dropped; \ 605 data[i++] += sta->rx_dropped; \
600 \ 606 \
601 data[i++] += sta->tx_packets; \ 607 data[i++] += sinfo.tx_packets; \
602 data[i++] += sta->tx_bytes; \ 608 data[i++] += sinfo.tx_bytes; \
603 data[i++] += sta->tx_fragments; \ 609 data[i++] += sta->tx_fragments; \
604 data[i++] += sta->tx_filtered_count; \ 610 data[i++] += sta->tx_filtered_count; \
605 data[i++] += sta->tx_retry_failed; \ 611 data[i++] += sta->tx_retry_failed; \
@@ -621,13 +627,14 @@ static void ieee80211_get_et_stats(struct wiphy *wiphy,
621 if (!(sta && !WARN_ON(sta->sdata->dev != dev))) 627 if (!(sta && !WARN_ON(sta->sdata->dev != dev)))
622 goto do_survey; 628 goto do_survey;
623 629
630 sinfo.filled = 0;
631 sta_set_sinfo(sta, &sinfo);
632
624 i = 0; 633 i = 0;
625 ADD_STA_STATS(sta); 634 ADD_STA_STATS(sta);
626 635
627 data[i++] = sta->sta_state; 636 data[i++] = sta->sta_state;
628 637
629 sinfo.filled = 0;
630 sta_set_sinfo(sta, &sinfo);
631 638
632 if (sinfo.filled & STATION_INFO_TX_BITRATE) 639 if (sinfo.filled & STATION_INFO_TX_BITRATE)
633 data[i] = 100000 * 640 data[i] = 100000 *