forked from Minki/linux
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>
This commit is contained in:
parent
d4f2cecce1
commit
b7f514af7d
@ -341,12 +341,12 @@ void falcon_update_stats_xmac(struct efx_nic *efx)
|
|||||||
FALCON_STAT(efx, XgTxIpSrcErrPkt, tx_ip_src_error);
|
FALCON_STAT(efx, XgTxIpSrcErrPkt, tx_ip_src_error);
|
||||||
|
|
||||||
/* Update derived statistics */
|
/* Update derived statistics */
|
||||||
mac_stats->tx_good_bytes =
|
efx_update_diff_stat(&mac_stats->tx_good_bytes,
|
||||||
(mac_stats->tx_bytes - mac_stats->tx_bad_bytes -
|
mac_stats->tx_bytes - mac_stats->tx_bad_bytes -
|
||||||
mac_stats->tx_control * 64);
|
mac_stats->tx_control * 64);
|
||||||
mac_stats->rx_bad_bytes =
|
efx_update_diff_stat(&mac_stats->rx_bad_bytes,
|
||||||
(mac_stats->rx_bytes - mac_stats->rx_good_bytes -
|
mac_stats->rx_bytes - mac_stats->rx_good_bytes -
|
||||||
mac_stats->rx_control * 64);
|
mac_stats->rx_control * 64);
|
||||||
}
|
}
|
||||||
|
|
||||||
void falcon_poll_xmac(struct efx_nic *efx)
|
void falcon_poll_xmac(struct efx_nic *efx)
|
||||||
|
@ -294,6 +294,24 @@ extern bool falcon_xmac_check_fault(struct efx_nic *efx);
|
|||||||
extern int falcon_reconfigure_xmac(struct efx_nic *efx);
|
extern int falcon_reconfigure_xmac(struct efx_nic *efx);
|
||||||
extern void falcon_update_stats_xmac(struct efx_nic *efx);
|
extern void falcon_update_stats_xmac(struct efx_nic *efx);
|
||||||
|
|
||||||
|
/* Some statistics are computed as A - B where A and B each increase
|
||||||
|
* linearly with some hardware counter(s) and the counters are read
|
||||||
|
* asynchronously. If the counters contributing to B are always read
|
||||||
|
* after those contributing to A, the computed value may be lower than
|
||||||
|
* the true value by some variable amount, and may decrease between
|
||||||
|
* subsequent computations.
|
||||||
|
*
|
||||||
|
* We should never allow statistics to decrease or to exceed the true
|
||||||
|
* value. Since the computed value will never be greater than the
|
||||||
|
* true value, we can achieve this by only storing the computed value
|
||||||
|
* when it increases.
|
||||||
|
*/
|
||||||
|
static inline void efx_update_diff_stat(u64 *stat, u64 diff)
|
||||||
|
{
|
||||||
|
if ((s64)(diff - *stat) > 0)
|
||||||
|
*stat = diff;
|
||||||
|
}
|
||||||
|
|
||||||
/* Interrupts and test events */
|
/* Interrupts and test events */
|
||||||
extern int efx_nic_init_interrupt(struct efx_nic *efx);
|
extern int efx_nic_init_interrupt(struct efx_nic *efx);
|
||||||
extern void efx_nic_enable_interrupts(struct efx_nic *efx);
|
extern void efx_nic_enable_interrupts(struct efx_nic *efx);
|
||||||
|
@ -458,8 +458,8 @@ static int siena_try_update_nic_stats(struct efx_nic *efx)
|
|||||||
|
|
||||||
MAC_STAT(tx_bytes, TX_BYTES);
|
MAC_STAT(tx_bytes, TX_BYTES);
|
||||||
MAC_STAT(tx_bad_bytes, TX_BAD_BYTES);
|
MAC_STAT(tx_bad_bytes, TX_BAD_BYTES);
|
||||||
mac_stats->tx_good_bytes = (mac_stats->tx_bytes -
|
efx_update_diff_stat(&mac_stats->tx_good_bytes,
|
||||||
mac_stats->tx_bad_bytes);
|
mac_stats->tx_bytes - mac_stats->tx_bad_bytes);
|
||||||
MAC_STAT(tx_packets, TX_PKTS);
|
MAC_STAT(tx_packets, TX_PKTS);
|
||||||
MAC_STAT(tx_bad, TX_BAD_FCS_PKTS);
|
MAC_STAT(tx_bad, TX_BAD_FCS_PKTS);
|
||||||
MAC_STAT(tx_pause, TX_PAUSE_PKTS);
|
MAC_STAT(tx_pause, TX_PAUSE_PKTS);
|
||||||
@ -492,8 +492,8 @@ static int siena_try_update_nic_stats(struct efx_nic *efx)
|
|||||||
MAC_STAT(tx_ip_src_error, TX_IP_SRC_ERR_PKTS);
|
MAC_STAT(tx_ip_src_error, TX_IP_SRC_ERR_PKTS);
|
||||||
MAC_STAT(rx_bytes, RX_BYTES);
|
MAC_STAT(rx_bytes, RX_BYTES);
|
||||||
MAC_STAT(rx_bad_bytes, RX_BAD_BYTES);
|
MAC_STAT(rx_bad_bytes, RX_BAD_BYTES);
|
||||||
mac_stats->rx_good_bytes = (mac_stats->rx_bytes -
|
efx_update_diff_stat(&mac_stats->rx_good_bytes,
|
||||||
mac_stats->rx_bad_bytes);
|
mac_stats->rx_bytes - mac_stats->rx_bad_bytes);
|
||||||
MAC_STAT(rx_packets, RX_PKTS);
|
MAC_STAT(rx_packets, RX_PKTS);
|
||||||
MAC_STAT(rx_good, RX_GOOD_PKTS);
|
MAC_STAT(rx_good, RX_GOOD_PKTS);
|
||||||
MAC_STAT(rx_bad, RX_BAD_FCS_PKTS);
|
MAC_STAT(rx_bad, RX_BAD_FCS_PKTS);
|
||||||
|
Loading…
Reference in New Issue
Block a user