From 0885a30b699a2c96d892b61cc48e8ba68fe87bfc Mon Sep 17 00:00:00 2001 From: stephen hemminger Date: Fri, 31 Dec 2010 15:34:27 +0000 Subject: sky2: implement 64 bit stats This implements 64 bit statistics support and fixes races when reading counter values. The PHY counters can only be accessed 16 bits at a time, so they are subject to carry races. NB: * TX/RX counters are maintained in software because the the hardware packet count is only a 32 bit value. * Error counters are really only 32 bit. * Old 32 bit counter fields in dev->stats still used for some software counters Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/sky2.h | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) (limited to 'drivers/net/sky2.h') diff --git a/drivers/net/sky2.h b/drivers/net/sky2.h index 61891a6cacc..80bdc404f1e 100644 --- a/drivers/net/sky2.h +++ b/drivers/net/sky2.h @@ -2200,6 +2200,12 @@ enum flow_control { FC_BOTH = 3, }; +struct sky2_stats { + struct u64_stats_sync syncp; + u64 packets; + u64 bytes; +}; + struct sky2_port { struct sky2_hw *hw; struct net_device *netdev; @@ -2209,6 +2215,8 @@ struct sky2_port { struct tx_ring_info *tx_ring; struct sky2_tx_le *tx_le; + struct sky2_stats tx_stats; + u16 tx_ring_size; u16 tx_cons; /* next le to check */ u16 tx_prod; /* next le to use */ @@ -2221,6 +2229,7 @@ struct sky2_port { struct rx_ring_info *rx_ring ____cacheline_aligned_in_smp; struct sky2_rx_le *rx_le; + struct sky2_stats rx_stats; u16 rx_next; /* next re to check */ u16 rx_put; /* next le index to use */ @@ -2346,6 +2355,39 @@ static inline u32 gma_read32(struct sky2_hw *hw, unsigned port, unsigned reg) | (u32) sky2_read16(hw, base+4) << 16; } +static inline u64 gma_read64(struct sky2_hw *hw, unsigned port, unsigned reg) +{ + unsigned base = SK_GMAC_REG(port, reg); + + return (u64) sky2_read16(hw, base) + | (u64) sky2_read16(hw, base+4) << 16 + | (u64) sky2_read16(hw, base+8) << 32 + | (u64) sky2_read16(hw, base+12) << 48; +} + +/* There is no way to atomically read32 bit values from PHY, so retry */ +static inline u32 get_stats32(struct sky2_hw *hw, unsigned port, unsigned reg) +{ + u32 val; + + do { + val = gma_read32(hw, port, reg); + } while (gma_read32(hw, port, reg) != val); + + return val; +} + +static inline u64 get_stats64(struct sky2_hw *hw, unsigned port, unsigned reg) +{ + u64 val; + + do { + val = gma_read64(hw, port, reg); + } while (gma_read64(hw, port, reg) != val); + + return val; +} + static inline void gma_write16(const struct sky2_hw *hw, unsigned port, int r, u16 v) { sky2_write16(hw, SK_GMAC_REG(port,r), v); -- cgit v1.2.3-18-g5258