aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/sky2.c
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.c
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.c')
-rw-r--r--drivers/net/sky2.c103
1 files changed, 67 insertions, 36 deletions
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c
index 0d4a236c3bb3..39996bf3b247 100644
--- a/drivers/net/sky2.c
+++ b/drivers/net/sky2.c
@@ -1917,8 +1917,10 @@ static void sky2_tx_complete(struct sky2_port *sky2, u16 done)
1917 netif_printk(sky2, tx_done, KERN_DEBUG, dev, 1917 netif_printk(sky2, tx_done, KERN_DEBUG, dev,
1918 "tx done %u\n", idx); 1918 "tx done %u\n", idx);
1919 1919
1920 dev->stats.tx_packets++; 1920 u64_stats_update_begin(&sky2->tx_stats.syncp);
1921 dev->stats.tx_bytes += skb->len; 1921 ++sky2->tx_stats.packets;
1922 sky2->tx_stats.bytes += skb->len;
1923 u64_stats_update_end(&sky2->tx_stats.syncp);
1922 1924
1923 re->skb = NULL; 1925 re->skb = NULL;
1924 dev_kfree_skb_any(skb); 1926 dev_kfree_skb_any(skb);
@@ -2460,7 +2462,7 @@ static struct sk_buff *sky2_receive(struct net_device *dev,
2460 2462
2461 /* if length reported by DMA does not match PHY, packet was truncated */ 2463 /* if length reported by DMA does not match PHY, packet was truncated */
2462 if (length != count) 2464 if (length != count)
2463 goto len_error; 2465 goto error;
2464 2466
2465okay: 2467okay:
2466 if (length < copybreak) 2468 if (length < copybreak)
@@ -2475,34 +2477,13 @@ resubmit:
2475 2477
2476 return skb; 2478 return skb;
2477 2479
2478len_error:
2479 /* Truncation of overlength packets
2480 causes PHY length to not match MAC length */
2481 ++dev->stats.rx_length_errors;
2482 if (net_ratelimit())
2483 netif_info(sky2, rx_err, dev,
2484 "rx length error: status %#x length %d\n",
2485 status, length);
2486 goto resubmit;
2487
2488error: 2480error:
2489 ++dev->stats.rx_errors; 2481 ++dev->stats.rx_errors;
2490 if (status & GMR_FS_RX_FF_OV) {
2491 dev->stats.rx_over_errors++;
2492 goto resubmit;
2493 }
2494 2482
2495 if (net_ratelimit()) 2483 if (net_ratelimit())
2496 netif_info(sky2, rx_err, dev, 2484 netif_info(sky2, rx_err, dev,
2497 "rx error, status 0x%x length %d\n", status, length); 2485 "rx error, status 0x%x length %d\n", status, length);
2498 2486
2499 if (status & (GMR_FS_LONG_ERR | GMR_FS_UN_SIZE))
2500 dev->stats.rx_length_errors++;
2501 if (status & GMR_FS_FRAGMENT)
2502 dev->stats.rx_frame_errors++;
2503 if (status & GMR_FS_CRC_ERR)
2504 dev->stats.rx_crc_errors++;
2505
2506 goto resubmit; 2487 goto resubmit;
2507} 2488}
2508 2489
@@ -2543,14 +2524,19 @@ static inline void sky2_skb_rx(const struct sky2_port *sky2,
2543static inline void sky2_rx_done(struct sky2_hw *hw, unsigned port, 2524static inline void sky2_rx_done(struct sky2_hw *hw, unsigned port,
2544 unsigned packets, unsigned bytes) 2525 unsigned packets, unsigned bytes)
2545{ 2526{
2546 if (packets) { 2527 struct net_device *dev = hw->dev[port];
2547 struct net_device *dev = hw->dev[port]; 2528 struct sky2_port *sky2 = netdev_priv(dev);
2548 2529
2549 dev->stats.rx_packets += packets; 2530 if (packets == 0)
2550 dev->stats.rx_bytes += bytes; 2531 return;
2551 dev->last_rx = jiffies; 2532
2552 sky2_rx_update(netdev_priv(dev), rxqaddr[port]); 2533 u64_stats_update_begin(&sky2->rx_stats.syncp);
2553 } 2534 sky2->rx_stats.packets += packets;
2535 sky2->rx_stats.bytes += bytes;
2536 u64_stats_update_end(&sky2->rx_stats.syncp);
2537
2538 dev->last_rx = jiffies;
2539 sky2_rx_update(netdev_priv(dev), rxqaddr[port]);
2554} 2540}
2555 2541
2556static void sky2_rx_checksum(struct sky2_port *sky2, u32 status) 2542static void sky2_rx_checksum(struct sky2_port *sky2, u32 status)
@@ -3626,13 +3612,11 @@ static void sky2_phy_stats(struct sky2_port *sky2, u64 * data, unsigned count)
3626 unsigned port = sky2->port; 3612 unsigned port = sky2->port;
3627 int i; 3613 int i;
3628 3614
3629 data[0] = (u64) gma_read32(hw, port, GM_TXO_OK_HI) << 32 3615 data[0] = get_stats64(hw, port, GM_TXO_OK_LO);
3630 | (u64) gma_read32(hw, port, GM_TXO_OK_LO); 3616 data[1] = get_stats64(hw, port, GM_RXO_OK_LO);
3631 data[1] = (u64) gma_read32(hw, port, GM_RXO_OK_HI) << 32
3632 | (u64) gma_read32(hw, port, GM_RXO_OK_LO);
3633 3617
3634 for (i = 2; i < count; i++) 3618 for (i = 2; i < count; i++)
3635 data[i] = (u64) gma_read32(hw, port, sky2_stats[i].offset); 3619 data[i] = get_stats32(hw, port, sky2_stats[i].offset);
3636} 3620}
3637 3621
3638static void sky2_set_msglevel(struct net_device *netdev, u32 value) 3622static void sky2_set_msglevel(struct net_device *netdev, u32 value)
@@ -3750,6 +3734,51 @@ static void sky2_set_multicast(struct net_device *dev)
3750 gma_write16(hw, port, GM_RX_CTRL, reg); 3734 gma_write16(hw, port, GM_RX_CTRL, reg);
3751} 3735}
3752 3736
3737static struct rtnl_link_stats64 *sky2_get_stats(struct net_device *dev,
3738 struct rtnl_link_stats64 *stats)
3739{
3740 struct sky2_port *sky2 = netdev_priv(dev);
3741 struct sky2_hw *hw = sky2->hw;
3742 unsigned port = sky2->port;
3743 unsigned int start;
3744 u64 _bytes, _packets;
3745
3746 do {
3747 start = u64_stats_fetch_begin_bh(&sky2->rx_stats.syncp);
3748 _bytes = sky2->rx_stats.bytes;
3749 _packets = sky2->rx_stats.packets;
3750 } while (u64_stats_fetch_retry_bh(&sky2->rx_stats.syncp, start));
3751
3752 stats->rx_packets = _packets;
3753 stats->rx_bytes = _bytes;
3754
3755 do {
3756 start = u64_stats_fetch_begin_bh(&sky2->tx_stats.syncp);
3757 _bytes = sky2->tx_stats.bytes;
3758 _packets = sky2->tx_stats.packets;
3759 } while (u64_stats_fetch_retry_bh(&sky2->tx_stats.syncp, start));
3760
3761 stats->tx_packets = _packets;
3762 stats->tx_bytes = _bytes;
3763
3764 stats->multicast = get_stats32(hw, port, GM_RXF_MC_OK)
3765 + get_stats32(hw, port, GM_RXF_BC_OK);
3766
3767 stats->collisions = get_stats32(hw, port, GM_TXF_COL);
3768
3769 stats->rx_length_errors = get_stats32(hw, port, GM_RXF_LNG_ERR);
3770 stats->rx_crc_errors = get_stats32(hw, port, GM_RXF_FCS_ERR);
3771 stats->rx_frame_errors = get_stats32(hw, port, GM_RXF_SHT)
3772 + get_stats32(hw, port, GM_RXE_FRAG);
3773 stats->rx_over_errors = get_stats32(hw, port, GM_RXE_FIFO_OV);
3774
3775 stats->rx_dropped = dev->stats.rx_dropped;
3776 stats->rx_fifo_errors = dev->stats.rx_fifo_errors;
3777 stats->tx_fifo_errors = dev->stats.tx_fifo_errors;
3778
3779 return stats;
3780}
3781
3753/* Can have one global because blinking is controlled by 3782/* Can have one global because blinking is controlled by
3754 * ethtool and that is always under RTNL mutex 3783 * ethtool and that is always under RTNL mutex
3755 */ 3784 */
@@ -4524,6 +4553,7 @@ static const struct net_device_ops sky2_netdev_ops[2] = {
4524 .ndo_set_multicast_list = sky2_set_multicast, 4553 .ndo_set_multicast_list = sky2_set_multicast,
4525 .ndo_change_mtu = sky2_change_mtu, 4554 .ndo_change_mtu = sky2_change_mtu,
4526 .ndo_tx_timeout = sky2_tx_timeout, 4555 .ndo_tx_timeout = sky2_tx_timeout,
4556 .ndo_get_stats64 = sky2_get_stats,
4527#ifdef SKY2_VLAN_TAG_USED 4557#ifdef SKY2_VLAN_TAG_USED
4528 .ndo_vlan_rx_register = sky2_vlan_rx_register, 4558 .ndo_vlan_rx_register = sky2_vlan_rx_register,
4529#endif 4559#endif
@@ -4541,6 +4571,7 @@ static const struct net_device_ops sky2_netdev_ops[2] = {
4541 .ndo_set_multicast_list = sky2_set_multicast, 4571 .ndo_set_multicast_list = sky2_set_multicast,
4542 .ndo_change_mtu = sky2_change_mtu, 4572 .ndo_change_mtu = sky2_change_mtu,
4543 .ndo_tx_timeout = sky2_tx_timeout, 4573 .ndo_tx_timeout = sky2_tx_timeout,
4574 .ndo_get_stats64 = sky2_get_stats,
4544#ifdef SKY2_VLAN_TAG_USED 4575#ifdef SKY2_VLAN_TAG_USED
4545 .ndo_vlan_rx_register = sky2_vlan_rx_register, 4576 .ndo_vlan_rx_register = sky2_vlan_rx_register,
4546#endif 4577#endif