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:
committed by
David S. Miller
parent
a016892cd6
commit
0885a30b69
@@ -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);
|
||||
|
Reference in New Issue
Block a user