typhoon: fix a race in typhoon_do_get_stats

Its important to store 'final' values in counters,
not using them as temporary variables,
or this might break some SNMP applications.

Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
Acked-by: David Dillow <dave@thedillows.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Eric Dumazet 2010-08-24 04:18:13 +00:00 committed by David S. Miller
parent 884c06f477
commit 21ff2929ed

View File

@ -962,36 +962,34 @@ typhoon_do_get_stats(struct typhoon *tp)
* The extra status reported would be a good candidate for
* ethtool_ops->get_{strings,stats}()
*/
stats->tx_packets = le32_to_cpu(s->txPackets);
stats->tx_bytes = le64_to_cpu(s->txBytes);
stats->tx_errors = le32_to_cpu(s->txCarrierLost);
stats->tx_carrier_errors = le32_to_cpu(s->txCarrierLost);
stats->collisions = le32_to_cpu(s->txMultipleCollisions);
stats->rx_packets = le32_to_cpu(s->rxPacketsGood);
stats->rx_bytes = le64_to_cpu(s->rxBytesGood);
stats->rx_fifo_errors = le32_to_cpu(s->rxFifoOverruns);
stats->tx_packets = le32_to_cpu(s->txPackets) +
saved->tx_packets;
stats->tx_bytes = le64_to_cpu(s->txBytes) +
saved->tx_bytes;
stats->tx_errors = le32_to_cpu(s->txCarrierLost) +
saved->tx_errors;
stats->tx_carrier_errors = le32_to_cpu(s->txCarrierLost) +
saved->tx_carrier_errors;
stats->collisions = le32_to_cpu(s->txMultipleCollisions) +
saved->collisions;
stats->rx_packets = le32_to_cpu(s->rxPacketsGood) +
saved->rx_packets;
stats->rx_bytes = le64_to_cpu(s->rxBytesGood) +
saved->rx_bytes;
stats->rx_fifo_errors = le32_to_cpu(s->rxFifoOverruns) +
saved->rx_fifo_errors;
stats->rx_errors = le32_to_cpu(s->rxFifoOverruns) +
le32_to_cpu(s->BadSSD) + le32_to_cpu(s->rxCrcErrors);
stats->rx_crc_errors = le32_to_cpu(s->rxCrcErrors);
stats->rx_length_errors = le32_to_cpu(s->rxOversized);
le32_to_cpu(s->BadSSD) + le32_to_cpu(s->rxCrcErrors) +
saved->rx_errors;
stats->rx_crc_errors = le32_to_cpu(s->rxCrcErrors) +
saved->rx_crc_errors;
stats->rx_length_errors = le32_to_cpu(s->rxOversized) +
saved->rx_length_errors;
tp->speed = (s->linkStatus & TYPHOON_LINK_100MBPS) ?
SPEED_100 : SPEED_10;
tp->duplex = (s->linkStatus & TYPHOON_LINK_FULL_DUPLEX) ?
DUPLEX_FULL : DUPLEX_HALF;
/* add in the saved statistics
*/
stats->tx_packets += saved->tx_packets;
stats->tx_bytes += saved->tx_bytes;
stats->tx_errors += saved->tx_errors;
stats->collisions += saved->collisions;
stats->rx_packets += saved->rx_packets;
stats->rx_bytes += saved->rx_bytes;
stats->rx_fifo_errors += saved->rx_fifo_errors;
stats->rx_errors += saved->rx_errors;
stats->rx_crc_errors += saved->rx_crc_errors;
stats->rx_length_errors += saved->rx_length_errors;
return 0;
}