aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Dumazet <eric.dumazet@gmail.com>2010-08-24 00:18:13 -0400
committerDavid S. Miller <davem@davemloft.net>2010-08-25 19:36:49 -0400
commit21ff2929edc89397cc4c621d3c3f842994640acd (patch)
tree46f75007ed886061101d05e2acfd9901ffa3d3ec
parent884c06f4777c598ea7bf4fbc7557ff2fca066f63 (diff)
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>
-rw-r--r--drivers/net/typhoon.c46
1 files changed, 22 insertions, 24 deletions
diff --git a/drivers/net/typhoon.c b/drivers/net/typhoon.c
index 2e50077ff450..3f4681f78262 100644
--- a/drivers/net/typhoon.c
+++ b/drivers/net/typhoon.c
@@ -962,36 +962,34 @@ typhoon_do_get_stats(struct typhoon *tp)
962 * The extra status reported would be a good candidate for 962 * The extra status reported would be a good candidate for
963 * ethtool_ops->get_{strings,stats}() 963 * ethtool_ops->get_{strings,stats}()
964 */ 964 */
965 stats->tx_packets = le32_to_cpu(s->txPackets); 965 stats->tx_packets = le32_to_cpu(s->txPackets) +
966 stats->tx_bytes = le64_to_cpu(s->txBytes); 966 saved->tx_packets;
967 stats->tx_errors = le32_to_cpu(s->txCarrierLost); 967 stats->tx_bytes = le64_to_cpu(s->txBytes) +
968 stats->tx_carrier_errors = le32_to_cpu(s->txCarrierLost); 968 saved->tx_bytes;
969 stats->collisions = le32_to_cpu(s->txMultipleCollisions); 969 stats->tx_errors = le32_to_cpu(s->txCarrierLost) +
970 stats->rx_packets = le32_to_cpu(s->rxPacketsGood); 970 saved->tx_errors;
971 stats->rx_bytes = le64_to_cpu(s->rxBytesGood); 971 stats->tx_carrier_errors = le32_to_cpu(s->txCarrierLost) +
972 stats->rx_fifo_errors = le32_to_cpu(s->rxFifoOverruns); 972 saved->tx_carrier_errors;
973 stats->collisions = le32_to_cpu(s->txMultipleCollisions) +
974 saved->collisions;
975 stats->rx_packets = le32_to_cpu(s->rxPacketsGood) +
976 saved->rx_packets;
977 stats->rx_bytes = le64_to_cpu(s->rxBytesGood) +
978 saved->rx_bytes;
979 stats->rx_fifo_errors = le32_to_cpu(s->rxFifoOverruns) +
980 saved->rx_fifo_errors;
973 stats->rx_errors = le32_to_cpu(s->rxFifoOverruns) + 981 stats->rx_errors = le32_to_cpu(s->rxFifoOverruns) +
974 le32_to_cpu(s->BadSSD) + le32_to_cpu(s->rxCrcErrors); 982 le32_to_cpu(s->BadSSD) + le32_to_cpu(s->rxCrcErrors) +
975 stats->rx_crc_errors = le32_to_cpu(s->rxCrcErrors); 983 saved->rx_errors;
976 stats->rx_length_errors = le32_to_cpu(s->rxOversized); 984 stats->rx_crc_errors = le32_to_cpu(s->rxCrcErrors) +
985 saved->rx_crc_errors;
986 stats->rx_length_errors = le32_to_cpu(s->rxOversized) +
987 saved->rx_length_errors;
977 tp->speed = (s->linkStatus & TYPHOON_LINK_100MBPS) ? 988 tp->speed = (s->linkStatus & TYPHOON_LINK_100MBPS) ?
978 SPEED_100 : SPEED_10; 989 SPEED_100 : SPEED_10;
979 tp->duplex = (s->linkStatus & TYPHOON_LINK_FULL_DUPLEX) ? 990 tp->duplex = (s->linkStatus & TYPHOON_LINK_FULL_DUPLEX) ?
980 DUPLEX_FULL : DUPLEX_HALF; 991 DUPLEX_FULL : DUPLEX_HALF;
981 992
982 /* add in the saved statistics
983 */
984 stats->tx_packets += saved->tx_packets;
985 stats->tx_bytes += saved->tx_bytes;
986 stats->tx_errors += saved->tx_errors;
987 stats->collisions += saved->collisions;
988 stats->rx_packets += saved->rx_packets;
989 stats->rx_bytes += saved->rx_bytes;
990 stats->rx_fifo_errors += saved->rx_fifo_errors;
991 stats->rx_errors += saved->rx_errors;
992 stats->rx_crc_errors += saved->rx_crc_errors;
993 stats->rx_length_errors += saved->rx_length_errors;
994
995 return 0; 993 return 0;
996} 994}
997 995