diff options
author | stephen hemminger <shemminger@vyatta.com> | 2010-12-31 10:34:27 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-01-01 17:02:24 -0500 |
commit | 0885a30b699a2c96d892b61cc48e8ba68fe87bfc (patch) | |
tree | 870ab51f527bc7369190075682e739b274f01803 /drivers/net/sky2.h | |
parent | a016892cd6eb8d3dd9769021b088917ac7371abd (diff) |
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>
Diffstat (limited to 'drivers/net/sky2.h')
-rw-r--r-- | drivers/net/sky2.h | 42 |
1 files changed, 42 insertions, 0 deletions
diff --git a/drivers/net/sky2.h b/drivers/net/sky2.h index 61891a6cacc2..80bdc404f1ea 100644 --- a/drivers/net/sky2.h +++ b/drivers/net/sky2.h | |||
@@ -2200,6 +2200,12 @@ enum flow_control { | |||
2200 | FC_BOTH = 3, | 2200 | FC_BOTH = 3, |
2201 | }; | 2201 | }; |
2202 | 2202 | ||
2203 | struct sky2_stats { | ||
2204 | struct u64_stats_sync syncp; | ||
2205 | u64 packets; | ||
2206 | u64 bytes; | ||
2207 | }; | ||
2208 | |||
2203 | struct sky2_port { | 2209 | struct sky2_port { |
2204 | struct sky2_hw *hw; | 2210 | struct sky2_hw *hw; |
2205 | struct net_device *netdev; | 2211 | struct net_device *netdev; |
@@ -2209,6 +2215,8 @@ struct sky2_port { | |||
2209 | 2215 | ||
2210 | struct tx_ring_info *tx_ring; | 2216 | struct tx_ring_info *tx_ring; |
2211 | struct sky2_tx_le *tx_le; | 2217 | struct sky2_tx_le *tx_le; |
2218 | struct sky2_stats tx_stats; | ||
2219 | |||
2212 | u16 tx_ring_size; | 2220 | u16 tx_ring_size; |
2213 | u16 tx_cons; /* next le to check */ | 2221 | u16 tx_cons; /* next le to check */ |
2214 | u16 tx_prod; /* next le to use */ | 2222 | u16 tx_prod; /* next le to use */ |
@@ -2221,6 +2229,7 @@ struct sky2_port { | |||
2221 | 2229 | ||
2222 | struct rx_ring_info *rx_ring ____cacheline_aligned_in_smp; | 2230 | struct rx_ring_info *rx_ring ____cacheline_aligned_in_smp; |
2223 | struct sky2_rx_le *rx_le; | 2231 | struct sky2_rx_le *rx_le; |
2232 | struct sky2_stats rx_stats; | ||
2224 | 2233 | ||
2225 | u16 rx_next; /* next re to check */ | 2234 | u16 rx_next; /* next re to check */ |
2226 | u16 rx_put; /* next le index to use */ | 2235 | 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) | |||
2346 | | (u32) sky2_read16(hw, base+4) << 16; | 2355 | | (u32) sky2_read16(hw, base+4) << 16; |
2347 | } | 2356 | } |
2348 | 2357 | ||
2358 | static inline u64 gma_read64(struct sky2_hw *hw, unsigned port, unsigned reg) | ||
2359 | { | ||
2360 | unsigned base = SK_GMAC_REG(port, reg); | ||
2361 | |||
2362 | return (u64) sky2_read16(hw, base) | ||
2363 | | (u64) sky2_read16(hw, base+4) << 16 | ||
2364 | | (u64) sky2_read16(hw, base+8) << 32 | ||
2365 | | (u64) sky2_read16(hw, base+12) << 48; | ||
2366 | } | ||
2367 | |||
2368 | /* There is no way to atomically read32 bit values from PHY, so retry */ | ||
2369 | static inline u32 get_stats32(struct sky2_hw *hw, unsigned port, unsigned reg) | ||
2370 | { | ||
2371 | u32 val; | ||
2372 | |||
2373 | do { | ||
2374 | val = gma_read32(hw, port, reg); | ||
2375 | } while (gma_read32(hw, port, reg) != val); | ||
2376 | |||
2377 | return val; | ||
2378 | } | ||
2379 | |||
2380 | static inline u64 get_stats64(struct sky2_hw *hw, unsigned port, unsigned reg) | ||
2381 | { | ||
2382 | u64 val; | ||
2383 | |||
2384 | do { | ||
2385 | val = gma_read64(hw, port, reg); | ||
2386 | } while (gma_read64(hw, port, reg) != val); | ||
2387 | |||
2388 | return val; | ||
2389 | } | ||
2390 | |||
2349 | static inline void gma_write16(const struct sky2_hw *hw, unsigned port, int r, u16 v) | 2391 | static inline void gma_write16(const struct sky2_hw *hw, unsigned port, int r, u16 v) |
2350 | { | 2392 | { |
2351 | sky2_write16(hw, SK_GMAC_REG(port,r), v); | 2393 | sky2_write16(hw, SK_GMAC_REG(port,r), v); |