diff options
author | Johannes Berg <johannes.berg@intel.com> | 2013-02-05 04:55:21 -0500 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2013-03-07 08:32:18 -0500 |
commit | 560d268220d3416a2d473bcc906ea2ccbf51e4ec (patch) | |
tree | 4cc83a5346d70fc14ec1874d9ad5c9714b64a0a0 /net/mac80211/cfg.c | |
parent | 87f59c70ce6d1abeaaf97594835be29f746b81a0 (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.c | 23 |
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 * |