aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/sky2.h
diff options
context:
space:
mode:
authorstephen hemminger <shemminger@vyatta.com>2010-12-31 10:34:27 -0500
committerDavid S. Miller <davem@davemloft.net>2011-01-01 17:02:24 -0500
commit0885a30b699a2c96d892b61cc48e8ba68fe87bfc (patch)
tree870ab51f527bc7369190075682e739b274f01803 /drivers/net/sky2.h
parenta016892cd6eb8d3dd9769021b088917ac7371abd (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.h42
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
2203struct sky2_stats {
2204 struct u64_stats_sync syncp;
2205 u64 packets;
2206 u64 bytes;
2207};
2208
2203struct sky2_port { 2209struct 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
2358static 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 */
2369static 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
2380static 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
2349static inline void gma_write16(const struct sky2_hw *hw, unsigned port, int r, u16 v) 2391static 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);