]> bbs.cooldavid.org Git - net-next-2.6.git/commitdiff
typhoon: fix a race in typhoon_do_get_stats
authorEric Dumazet <eric.dumazet@gmail.com>
Tue, 24 Aug 2010 04:18:13 +0000 (04:18 +0000)
committerDavid S. Miller <davem@davemloft.net>
Wed, 25 Aug 2010 23:36:49 +0000 (16:36 -0700)
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>
drivers/net/typhoon.c

index 2e50077ff450b249a9042259375b5288f41965c6..3f4681f78262caaf42af13b802758eb34667f209 100644 (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;
 }