aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/sfc
diff options
context:
space:
mode:
authorBen Hutchings <bhutchings@solarflare.com>2012-07-04 17:25:07 -0400
committerBen Hutchings <bhutchings@solarflare.com>2012-07-17 11:12:34 -0400
commitb7f514af7d6f36bc2f683e04a909c95e4744b95b (patch)
tree3e8919c3f81d3434d5252ede948d992a1a25deb0 /drivers/net/ethernet/sfc
parentd4f2cecce138c34960c467d0ae38a6d4bcd6af7b (diff)
sfc: Fix interface statistics running backward
Some interface statistics are computed in such a way that they can sometimes decrease (and even underflow). Since the computed value will never be greater than the true value, we fix this by only storing the computed value when it increases. Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
Diffstat (limited to 'drivers/net/ethernet/sfc')
-rw-r--r--drivers/net/ethernet/sfc/falcon_xmac.c12
-rw-r--r--drivers/net/ethernet/sfc/nic.h18
-rw-r--r--drivers/net/ethernet/sfc/siena.c8
3 files changed, 28 insertions, 10 deletions
diff --git a/drivers/net/ethernet/sfc/falcon_xmac.c b/drivers/net/ethernet/sfc/falcon_xmac.c
index 6106ef15dee3..8333865d4c95 100644
--- a/drivers/net/ethernet/sfc/falcon_xmac.c
+++ b/drivers/net/ethernet/sfc/falcon_xmac.c
@@ -341,12 +341,12 @@ void falcon_update_stats_xmac(struct efx_nic *efx)
341 FALCON_STAT(efx, XgTxIpSrcErrPkt, tx_ip_src_error); 341 FALCON_STAT(efx, XgTxIpSrcErrPkt, tx_ip_src_error);
342 342
343 /* Update derived statistics */ 343 /* Update derived statistics */
344 mac_stats->tx_good_bytes = 344 efx_update_diff_stat(&mac_stats->tx_good_bytes,
345 (mac_stats->tx_bytes - mac_stats->tx_bad_bytes - 345 mac_stats->tx_bytes - mac_stats->tx_bad_bytes -
346 mac_stats->tx_control * 64); 346 mac_stats->tx_control * 64);
347 mac_stats->rx_bad_bytes = 347 efx_update_diff_stat(&mac_stats->rx_bad_bytes,
348 (mac_stats->rx_bytes - mac_stats->rx_good_bytes - 348 mac_stats->rx_bytes - mac_stats->rx_good_bytes -
349 mac_stats->rx_control * 64); 349 mac_stats->rx_control * 64);
350} 350}
351 351
352void falcon_poll_xmac(struct efx_nic *efx) 352void falcon_poll_xmac(struct efx_nic *efx)
diff --git a/drivers/net/ethernet/sfc/nic.h b/drivers/net/ethernet/sfc/nic.h
index f48ccf6bb3b9..bab5cd9f5740 100644
--- a/drivers/net/ethernet/sfc/nic.h
+++ b/drivers/net/ethernet/sfc/nic.h
@@ -294,6 +294,24 @@ extern bool falcon_xmac_check_fault(struct efx_nic *efx);
294extern int falcon_reconfigure_xmac(struct efx_nic *efx); 294extern int falcon_reconfigure_xmac(struct efx_nic *efx);
295extern void falcon_update_stats_xmac(struct efx_nic *efx); 295extern void falcon_update_stats_xmac(struct efx_nic *efx);
296 296
297/* Some statistics are computed as A - B where A and B each increase
298 * linearly with some hardware counter(s) and the counters are read
299 * asynchronously. If the counters contributing to B are always read
300 * after those contributing to A, the computed value may be lower than
301 * the true value by some variable amount, and may decrease between
302 * subsequent computations.
303 *
304 * We should never allow statistics to decrease or to exceed the true
305 * value. Since the computed value will never be greater than the
306 * true value, we can achieve this by only storing the computed value
307 * when it increases.
308 */
309static inline void efx_update_diff_stat(u64 *stat, u64 diff)
310{
311 if ((s64)(diff - *stat) > 0)
312 *stat = diff;
313}
314
297/* Interrupts and test events */ 315/* Interrupts and test events */
298extern int efx_nic_init_interrupt(struct efx_nic *efx); 316extern int efx_nic_init_interrupt(struct efx_nic *efx);
299extern void efx_nic_enable_interrupts(struct efx_nic *efx); 317extern void efx_nic_enable_interrupts(struct efx_nic *efx);
diff --git a/drivers/net/ethernet/sfc/siena.c b/drivers/net/ethernet/sfc/siena.c
index 2354886293db..6bafd216e55e 100644
--- a/drivers/net/ethernet/sfc/siena.c
+++ b/drivers/net/ethernet/sfc/siena.c
@@ -458,8 +458,8 @@ static int siena_try_update_nic_stats(struct efx_nic *efx)
458 458
459 MAC_STAT(tx_bytes, TX_BYTES); 459 MAC_STAT(tx_bytes, TX_BYTES);
460 MAC_STAT(tx_bad_bytes, TX_BAD_BYTES); 460 MAC_STAT(tx_bad_bytes, TX_BAD_BYTES);
461 mac_stats->tx_good_bytes = (mac_stats->tx_bytes - 461 efx_update_diff_stat(&mac_stats->tx_good_bytes,
462 mac_stats->tx_bad_bytes); 462 mac_stats->tx_bytes - mac_stats->tx_bad_bytes);
463 MAC_STAT(tx_packets, TX_PKTS); 463 MAC_STAT(tx_packets, TX_PKTS);
464 MAC_STAT(tx_bad, TX_BAD_FCS_PKTS); 464 MAC_STAT(tx_bad, TX_BAD_FCS_PKTS);
465 MAC_STAT(tx_pause, TX_PAUSE_PKTS); 465 MAC_STAT(tx_pause, TX_PAUSE_PKTS);
@@ -492,8 +492,8 @@ static int siena_try_update_nic_stats(struct efx_nic *efx)
492 MAC_STAT(tx_ip_src_error, TX_IP_SRC_ERR_PKTS); 492 MAC_STAT(tx_ip_src_error, TX_IP_SRC_ERR_PKTS);
493 MAC_STAT(rx_bytes, RX_BYTES); 493 MAC_STAT(rx_bytes, RX_BYTES);
494 MAC_STAT(rx_bad_bytes, RX_BAD_BYTES); 494 MAC_STAT(rx_bad_bytes, RX_BAD_BYTES);
495 mac_stats->rx_good_bytes = (mac_stats->rx_bytes - 495 efx_update_diff_stat(&mac_stats->rx_good_bytes,
496 mac_stats->rx_bad_bytes); 496 mac_stats->rx_bytes - mac_stats->rx_bad_bytes);
497 MAC_STAT(rx_packets, RX_PKTS); 497 MAC_STAT(rx_packets, RX_PKTS);
498 MAC_STAT(rx_good, RX_GOOD_PKTS); 498 MAC_STAT(rx_good, RX_GOOD_PKTS);
499 MAC_STAT(rx_bad, RX_BAD_FCS_PKTS); 499 MAC_STAT(rx_bad, RX_BAD_FCS_PKTS);