Commit 560d268220d3416a2d473bcc906ea2ccbf51e4ec
1 parent
87f59c70ce
Exists in
smarc-l5.0.0_1.0.0-ga
and in
5 other branches
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>
Showing 3 changed files with 25 additions and 14 deletions Side-by-side Diff
net/mac80211/cfg.c
... | ... | @@ -445,12 +445,14 @@ |
445 | 445 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
446 | 446 | struct ieee80211_local *local = sdata->local; |
447 | 447 | struct timespec uptime; |
448 | + u64 packets = 0; | |
449 | + int ac; | |
448 | 450 | |
449 | 451 | sinfo->generation = sdata->local->sta_generation; |
450 | 452 | |
451 | 453 | sinfo->filled = STATION_INFO_INACTIVE_TIME | |
452 | - STATION_INFO_RX_BYTES | | |
453 | - STATION_INFO_TX_BYTES | | |
454 | + STATION_INFO_RX_BYTES64 | | |
455 | + STATION_INFO_TX_BYTES64 | | |
454 | 456 | STATION_INFO_RX_PACKETS | |
455 | 457 | STATION_INFO_TX_PACKETS | |
456 | 458 | STATION_INFO_TX_RETRIES | |
457 | 459 | |
458 | 460 | |
... | ... | @@ -467,10 +469,14 @@ |
467 | 469 | sinfo->connected_time = uptime.tv_sec - sta->last_connected; |
468 | 470 | |
469 | 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 | 478 | sinfo->rx_bytes = sta->rx_bytes; |
471 | - sinfo->tx_bytes = sta->tx_bytes; | |
472 | 479 | sinfo->rx_packets = sta->rx_packets; |
473 | - sinfo->tx_packets = sta->tx_packets; | |
474 | 480 | sinfo->tx_retries = sta->tx_retry_count; |
475 | 481 | sinfo->tx_failed = sta->tx_retry_failed; |
476 | 482 | sinfo->rx_dropped_misc = sta->rx_dropped; |
... | ... | @@ -598,8 +604,8 @@ |
598 | 604 | data[i++] += sta->rx_fragments; \ |
599 | 605 | data[i++] += sta->rx_dropped; \ |
600 | 606 | \ |
601 | - data[i++] += sta->tx_packets; \ | |
602 | - data[i++] += sta->tx_bytes; \ | |
607 | + data[i++] += sinfo.tx_packets; \ | |
608 | + data[i++] += sinfo.tx_bytes; \ | |
603 | 609 | data[i++] += sta->tx_fragments; \ |
604 | 610 | data[i++] += sta->tx_filtered_count; \ |
605 | 611 | data[i++] += sta->tx_retry_failed; \ |
606 | 612 | |
... | ... | @@ -621,13 +627,14 @@ |
621 | 627 | if (!(sta && !WARN_ON(sta->sdata->dev != dev))) |
622 | 628 | goto do_survey; |
623 | 629 | |
630 | + sinfo.filled = 0; | |
631 | + sta_set_sinfo(sta, &sinfo); | |
632 | + | |
624 | 633 | i = 0; |
625 | 634 | ADD_STA_STATS(sta); |
626 | 635 | |
627 | 636 | data[i++] = sta->sta_state; |
628 | 637 | |
629 | - sinfo.filled = 0; | |
630 | - sta_set_sinfo(sta, &sinfo); | |
631 | 638 | |
632 | 639 | if (sinfo.filled & STATION_INFO_TX_BITRATE) |
633 | 640 | data[i] = 100000 * |
net/mac80211/sta_info.h
... | ... | @@ -333,7 +333,8 @@ |
333 | 333 | unsigned long driver_buffered_tids; |
334 | 334 | |
335 | 335 | /* Updated from RX path only, no locking requirements */ |
336 | - unsigned long rx_packets, rx_bytes; | |
336 | + unsigned long rx_packets; | |
337 | + u64 rx_bytes; | |
337 | 338 | unsigned long wep_weak_iv_count; |
338 | 339 | unsigned long last_rx; |
339 | 340 | long last_connected; |
... | ... | @@ -353,9 +354,9 @@ |
353 | 354 | unsigned int fail_avg; |
354 | 355 | |
355 | 356 | /* Updated from TX path only, no locking requirements */ |
356 | - unsigned long tx_packets; | |
357 | - unsigned long tx_bytes; | |
358 | - unsigned long tx_fragments; | |
357 | + u32 tx_fragments; | |
358 | + u64 tx_packets[IEEE80211_NUM_ACS]; | |
359 | + u64 tx_bytes[IEEE80211_NUM_ACS]; | |
359 | 360 | struct ieee80211_tx_rate last_tx_rate; |
360 | 361 | int last_rx_rate_idx; |
361 | 362 | u32 last_rx_rate_flag; |
net/mac80211/tx.c
... | ... | @@ -991,15 +991,18 @@ |
991 | 991 | ieee80211_tx_h_stats(struct ieee80211_tx_data *tx) |
992 | 992 | { |
993 | 993 | struct sk_buff *skb; |
994 | + int ac = -1; | |
994 | 995 | |
995 | 996 | if (!tx->sta) |
996 | 997 | return TX_CONTINUE; |
997 | 998 | |
998 | - tx->sta->tx_packets++; | |
999 | 999 | skb_queue_walk(&tx->skbs, skb) { |
1000 | + ac = skb_get_queue_mapping(skb); | |
1000 | 1001 | tx->sta->tx_fragments++; |
1001 | - tx->sta->tx_bytes += skb->len; | |
1002 | + tx->sta->tx_bytes[ac] += skb->len; | |
1002 | 1003 | } |
1004 | + if (ac >= 0) | |
1005 | + tx->sta->tx_packets[ac]++; | |
1003 | 1006 | |
1004 | 1007 | return TX_CONTINUE; |
1005 | 1008 | } |