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 <shemminger@vyatta.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
stephen hemminger
2010-12-31 15:34:27 +00:00
committed by David S. Miller
parent a016892cd6
commit 0885a30b69
2 changed files with 109 additions and 36 deletions

View File

@@ -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);