diff options
author | Jeff Kirsher <jeffrey.t.kirsher@intel.com> | 2011-01-07 00:12:09 -0500 |
---|---|---|
committer | Jeff Kirsher <jeffrey.t.kirsher@intel.com> | 2011-01-24 03:13:37 -0500 |
commit | 67fd4fcb78a7ced369a6bd8a131ec8c65ebd2bbb (patch) | |
tree | 53747c0e34152d47c440f9dbb8318301747ccbab /drivers/net/e1000e | |
parent | bb134d2298b49f50cf6d9388410fba96272905dc (diff) |
e1000e: convert to stats64
Based on the patch provided by Flavio Leitner <fleitner@redhat.com>
Provides accurate stats at the time user reads them.
v2: fixed whitespace/merging issues (by Jeff Kirsher)
v3: fixed namespacing issues (by Bruce Allan)
CC: Eric Dumazet <eric.dumazet@gmail.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Tested-by: Jeff Pieper <jeffrey.e.pieper@intel.com>
Signed-off-by: Flavio Leitner <fleitner@redhat.com>
Diffstat (limited to 'drivers/net/e1000e')
-rw-r--r-- | drivers/net/e1000e/e1000.h | 5 | ||||
-rw-r--r-- | drivers/net/e1000e/ethtool.c | 37 | ||||
-rw-r--r-- | drivers/net/e1000e/netdev.c | 72 |
3 files changed, 80 insertions, 34 deletions
diff --git a/drivers/net/e1000e/e1000.h b/drivers/net/e1000e/e1000.h index e610e1369053..00bf595ebd67 100644 --- a/drivers/net/e1000e/e1000.h +++ b/drivers/net/e1000e/e1000.h | |||
@@ -364,6 +364,7 @@ struct e1000_adapter { | |||
364 | /* structs defined in e1000_hw.h */ | 364 | /* structs defined in e1000_hw.h */ |
365 | struct e1000_hw hw; | 365 | struct e1000_hw hw; |
366 | 366 | ||
367 | spinlock_t stats64_lock; | ||
367 | struct e1000_hw_stats stats; | 368 | struct e1000_hw_stats stats; |
368 | struct e1000_phy_info phy_info; | 369 | struct e1000_phy_info phy_info; |
369 | struct e1000_phy_stats phy_stats; | 370 | struct e1000_phy_stats phy_stats; |
@@ -494,7 +495,9 @@ extern int e1000e_setup_rx_resources(struct e1000_adapter *adapter); | |||
494 | extern int e1000e_setup_tx_resources(struct e1000_adapter *adapter); | 495 | extern int e1000e_setup_tx_resources(struct e1000_adapter *adapter); |
495 | extern void e1000e_free_rx_resources(struct e1000_adapter *adapter); | 496 | extern void e1000e_free_rx_resources(struct e1000_adapter *adapter); |
496 | extern void e1000e_free_tx_resources(struct e1000_adapter *adapter); | 497 | extern void e1000e_free_tx_resources(struct e1000_adapter *adapter); |
497 | extern void e1000e_update_stats(struct e1000_adapter *adapter); | 498 | extern struct rtnl_link_stats64 *e1000e_get_stats64(struct net_device *netdev, |
499 | struct rtnl_link_stats64 | ||
500 | *stats); | ||
498 | extern void e1000e_set_interrupt_capability(struct e1000_adapter *adapter); | 501 | extern void e1000e_set_interrupt_capability(struct e1000_adapter *adapter); |
499 | extern void e1000e_reset_interrupt_capability(struct e1000_adapter *adapter); | 502 | extern void e1000e_reset_interrupt_capability(struct e1000_adapter *adapter); |
500 | extern void e1000e_get_hw_control(struct e1000_adapter *adapter); | 503 | extern void e1000e_get_hw_control(struct e1000_adapter *adapter); |
diff --git a/drivers/net/e1000e/ethtool.c b/drivers/net/e1000e/ethtool.c index fa08b6336cfb..dfa44de9cf0d 100644 --- a/drivers/net/e1000e/ethtool.c +++ b/drivers/net/e1000e/ethtool.c | |||
@@ -46,15 +46,15 @@ struct e1000_stats { | |||
46 | }; | 46 | }; |
47 | 47 | ||
48 | #define E1000_STAT(str, m) { \ | 48 | #define E1000_STAT(str, m) { \ |
49 | .stat_string = str, \ | 49 | .stat_string = str, \ |
50 | .type = E1000_STATS, \ | 50 | .type = E1000_STATS, \ |
51 | .sizeof_stat = sizeof(((struct e1000_adapter *)0)->m), \ | 51 | .sizeof_stat = sizeof(((struct e1000_adapter *)0)->m), \ |
52 | .stat_offset = offsetof(struct e1000_adapter, m) } | 52 | .stat_offset = offsetof(struct e1000_adapter, m) } |
53 | #define E1000_NETDEV_STAT(str, m) { \ | 53 | #define E1000_NETDEV_STAT(str, m) { \ |
54 | .stat_string = str, \ | 54 | .stat_string = str, \ |
55 | .type = NETDEV_STATS, \ | 55 | .type = NETDEV_STATS, \ |
56 | .sizeof_stat = sizeof(((struct net_device *)0)->m), \ | 56 | .sizeof_stat = sizeof(((struct rtnl_link_stats64 *)0)->m), \ |
57 | .stat_offset = offsetof(struct net_device, m) } | 57 | .stat_offset = offsetof(struct rtnl_link_stats64, m) } |
58 | 58 | ||
59 | static const struct e1000_stats e1000_gstrings_stats[] = { | 59 | static const struct e1000_stats e1000_gstrings_stats[] = { |
60 | E1000_STAT("rx_packets", stats.gprc), | 60 | E1000_STAT("rx_packets", stats.gprc), |
@@ -65,21 +65,21 @@ static const struct e1000_stats e1000_gstrings_stats[] = { | |||
65 | E1000_STAT("tx_broadcast", stats.bptc), | 65 | E1000_STAT("tx_broadcast", stats.bptc), |
66 | E1000_STAT("rx_multicast", stats.mprc), | 66 | E1000_STAT("rx_multicast", stats.mprc), |
67 | E1000_STAT("tx_multicast", stats.mptc), | 67 | E1000_STAT("tx_multicast", stats.mptc), |
68 | E1000_NETDEV_STAT("rx_errors", stats.rx_errors), | 68 | E1000_NETDEV_STAT("rx_errors", rx_errors), |
69 | E1000_NETDEV_STAT("tx_errors", stats.tx_errors), | 69 | E1000_NETDEV_STAT("tx_errors", tx_errors), |
70 | E1000_NETDEV_STAT("tx_dropped", stats.tx_dropped), | 70 | E1000_NETDEV_STAT("tx_dropped", tx_dropped), |
71 | E1000_STAT("multicast", stats.mprc), | 71 | E1000_STAT("multicast", stats.mprc), |
72 | E1000_STAT("collisions", stats.colc), | 72 | E1000_STAT("collisions", stats.colc), |
73 | E1000_NETDEV_STAT("rx_length_errors", stats.rx_length_errors), | 73 | E1000_NETDEV_STAT("rx_length_errors", rx_length_errors), |
74 | E1000_NETDEV_STAT("rx_over_errors", stats.rx_over_errors), | 74 | E1000_NETDEV_STAT("rx_over_errors", rx_over_errors), |
75 | E1000_STAT("rx_crc_errors", stats.crcerrs), | 75 | E1000_STAT("rx_crc_errors", stats.crcerrs), |
76 | E1000_NETDEV_STAT("rx_frame_errors", stats.rx_frame_errors), | 76 | E1000_NETDEV_STAT("rx_frame_errors", rx_frame_errors), |
77 | E1000_STAT("rx_no_buffer_count", stats.rnbc), | 77 | E1000_STAT("rx_no_buffer_count", stats.rnbc), |
78 | E1000_STAT("rx_missed_errors", stats.mpc), | 78 | E1000_STAT("rx_missed_errors", stats.mpc), |
79 | E1000_STAT("tx_aborted_errors", stats.ecol), | 79 | E1000_STAT("tx_aborted_errors", stats.ecol), |
80 | E1000_STAT("tx_carrier_errors", stats.tncrs), | 80 | E1000_STAT("tx_carrier_errors", stats.tncrs), |
81 | E1000_NETDEV_STAT("tx_fifo_errors", stats.tx_fifo_errors), | 81 | E1000_NETDEV_STAT("tx_fifo_errors", tx_fifo_errors), |
82 | E1000_NETDEV_STAT("tx_heartbeat_errors", stats.tx_heartbeat_errors), | 82 | E1000_NETDEV_STAT("tx_heartbeat_errors", tx_heartbeat_errors), |
83 | E1000_STAT("tx_window_errors", stats.latecol), | 83 | E1000_STAT("tx_window_errors", stats.latecol), |
84 | E1000_STAT("tx_abort_late_coll", stats.latecol), | 84 | E1000_STAT("tx_abort_late_coll", stats.latecol), |
85 | E1000_STAT("tx_deferred_ok", stats.dc), | 85 | E1000_STAT("tx_deferred_ok", stats.dc), |
@@ -1982,14 +1982,15 @@ static void e1000_get_ethtool_stats(struct net_device *netdev, | |||
1982 | u64 *data) | 1982 | u64 *data) |
1983 | { | 1983 | { |
1984 | struct e1000_adapter *adapter = netdev_priv(netdev); | 1984 | struct e1000_adapter *adapter = netdev_priv(netdev); |
1985 | struct rtnl_link_stats64 net_stats; | ||
1985 | int i; | 1986 | int i; |
1986 | char *p = NULL; | 1987 | char *p = NULL; |
1987 | 1988 | ||
1988 | e1000e_update_stats(adapter); | 1989 | e1000e_get_stats64(netdev, &net_stats); |
1989 | for (i = 0; i < E1000_GLOBAL_STATS_LEN; i++) { | 1990 | for (i = 0; i < E1000_GLOBAL_STATS_LEN; i++) { |
1990 | switch (e1000_gstrings_stats[i].type) { | 1991 | switch (e1000_gstrings_stats[i].type) { |
1991 | case NETDEV_STATS: | 1992 | case NETDEV_STATS: |
1992 | p = (char *) netdev + | 1993 | p = (char *) &net_stats + |
1993 | e1000_gstrings_stats[i].stat_offset; | 1994 | e1000_gstrings_stats[i].stat_offset; |
1994 | break; | 1995 | break; |
1995 | case E1000_STATS: | 1996 | case E1000_STATS: |
diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index 1c18f26b0812..1c2f33dd0633 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c | |||
@@ -900,8 +900,6 @@ next_desc: | |||
900 | 900 | ||
901 | adapter->total_rx_bytes += total_rx_bytes; | 901 | adapter->total_rx_bytes += total_rx_bytes; |
902 | adapter->total_rx_packets += total_rx_packets; | 902 | adapter->total_rx_packets += total_rx_packets; |
903 | netdev->stats.rx_bytes += total_rx_bytes; | ||
904 | netdev->stats.rx_packets += total_rx_packets; | ||
905 | return cleaned; | 903 | return cleaned; |
906 | } | 904 | } |
907 | 905 | ||
@@ -1057,8 +1055,6 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter) | |||
1057 | } | 1055 | } |
1058 | adapter->total_tx_bytes += total_tx_bytes; | 1056 | adapter->total_tx_bytes += total_tx_bytes; |
1059 | adapter->total_tx_packets += total_tx_packets; | 1057 | adapter->total_tx_packets += total_tx_packets; |
1060 | netdev->stats.tx_bytes += total_tx_bytes; | ||
1061 | netdev->stats.tx_packets += total_tx_packets; | ||
1062 | return count < tx_ring->count; | 1058 | return count < tx_ring->count; |
1063 | } | 1059 | } |
1064 | 1060 | ||
@@ -1245,8 +1241,6 @@ next_desc: | |||
1245 | 1241 | ||
1246 | adapter->total_rx_bytes += total_rx_bytes; | 1242 | adapter->total_rx_bytes += total_rx_bytes; |
1247 | adapter->total_rx_packets += total_rx_packets; | 1243 | adapter->total_rx_packets += total_rx_packets; |
1248 | netdev->stats.rx_bytes += total_rx_bytes; | ||
1249 | netdev->stats.rx_packets += total_rx_packets; | ||
1250 | return cleaned; | 1244 | return cleaned; |
1251 | } | 1245 | } |
1252 | 1246 | ||
@@ -1426,8 +1420,6 @@ next_desc: | |||
1426 | 1420 | ||
1427 | adapter->total_rx_bytes += total_rx_bytes; | 1421 | adapter->total_rx_bytes += total_rx_bytes; |
1428 | adapter->total_rx_packets += total_rx_packets; | 1422 | adapter->total_rx_packets += total_rx_packets; |
1429 | netdev->stats.rx_bytes += total_rx_bytes; | ||
1430 | netdev->stats.rx_packets += total_rx_packets; | ||
1431 | return cleaned; | 1423 | return cleaned; |
1432 | } | 1424 | } |
1433 | 1425 | ||
@@ -3338,6 +3330,8 @@ int e1000e_up(struct e1000_adapter *adapter) | |||
3338 | return 0; | 3330 | return 0; |
3339 | } | 3331 | } |
3340 | 3332 | ||
3333 | static void e1000e_update_stats(struct e1000_adapter *adapter); | ||
3334 | |||
3341 | void e1000e_down(struct e1000_adapter *adapter) | 3335 | void e1000e_down(struct e1000_adapter *adapter) |
3342 | { | 3336 | { |
3343 | struct net_device *netdev = adapter->netdev; | 3337 | struct net_device *netdev = adapter->netdev; |
@@ -3372,6 +3366,11 @@ void e1000e_down(struct e1000_adapter *adapter) | |||
3372 | del_timer_sync(&adapter->phy_info_timer); | 3366 | del_timer_sync(&adapter->phy_info_timer); |
3373 | 3367 | ||
3374 | netif_carrier_off(netdev); | 3368 | netif_carrier_off(netdev); |
3369 | |||
3370 | spin_lock(&adapter->stats64_lock); | ||
3371 | e1000e_update_stats(adapter); | ||
3372 | spin_unlock(&adapter->stats64_lock); | ||
3373 | |||
3375 | adapter->link_speed = 0; | 3374 | adapter->link_speed = 0; |
3376 | adapter->link_duplex = 0; | 3375 | adapter->link_duplex = 0; |
3377 | 3376 | ||
@@ -3413,6 +3412,8 @@ static int __devinit e1000_sw_init(struct e1000_adapter *adapter) | |||
3413 | adapter->max_frame_size = netdev->mtu + ETH_HLEN + ETH_FCS_LEN; | 3412 | adapter->max_frame_size = netdev->mtu + ETH_HLEN + ETH_FCS_LEN; |
3414 | adapter->min_frame_size = ETH_ZLEN + ETH_FCS_LEN; | 3413 | adapter->min_frame_size = ETH_ZLEN + ETH_FCS_LEN; |
3415 | 3414 | ||
3415 | spin_lock_init(&adapter->stats64_lock); | ||
3416 | |||
3416 | e1000e_set_interrupt_capability(adapter); | 3417 | e1000e_set_interrupt_capability(adapter); |
3417 | 3418 | ||
3418 | if (e1000_alloc_queues(adapter)) | 3419 | if (e1000_alloc_queues(adapter)) |
@@ -3886,7 +3887,7 @@ release: | |||
3886 | * e1000e_update_stats - Update the board statistics counters | 3887 | * e1000e_update_stats - Update the board statistics counters |
3887 | * @adapter: board private structure | 3888 | * @adapter: board private structure |
3888 | **/ | 3889 | **/ |
3889 | void e1000e_update_stats(struct e1000_adapter *adapter) | 3890 | static void e1000e_update_stats(struct e1000_adapter *adapter) |
3890 | { | 3891 | { |
3891 | struct net_device *netdev = adapter->netdev; | 3892 | struct net_device *netdev = adapter->netdev; |
3892 | struct e1000_hw *hw = &adapter->hw; | 3893 | struct e1000_hw *hw = &adapter->hw; |
@@ -4285,7 +4286,9 @@ static void e1000_watchdog_task(struct work_struct *work) | |||
4285 | } | 4286 | } |
4286 | 4287 | ||
4287 | link_up: | 4288 | link_up: |
4289 | spin_lock(&adapter->stats64_lock); | ||
4288 | e1000e_update_stats(adapter); | 4290 | e1000e_update_stats(adapter); |
4291 | spin_unlock(&adapter->stats64_lock); | ||
4289 | 4292 | ||
4290 | mac->tx_packet_delta = adapter->stats.tpt - adapter->tpt_old; | 4293 | mac->tx_packet_delta = adapter->stats.tpt - adapter->tpt_old; |
4291 | adapter->tpt_old = adapter->stats.tpt; | 4294 | adapter->tpt_old = adapter->stats.tpt; |
@@ -4897,16 +4900,55 @@ static void e1000_reset_task(struct work_struct *work) | |||
4897 | } | 4900 | } |
4898 | 4901 | ||
4899 | /** | 4902 | /** |
4900 | * e1000_get_stats - Get System Network Statistics | 4903 | * e1000_get_stats64 - Get System Network Statistics |
4901 | * @netdev: network interface device structure | 4904 | * @netdev: network interface device structure |
4905 | * @stats: rtnl_link_stats64 pointer | ||
4902 | * | 4906 | * |
4903 | * Returns the address of the device statistics structure. | 4907 | * Returns the address of the device statistics structure. |
4904 | * The statistics are actually updated from the timer callback. | ||
4905 | **/ | 4908 | **/ |
4906 | static struct net_device_stats *e1000_get_stats(struct net_device *netdev) | 4909 | struct rtnl_link_stats64 *e1000e_get_stats64(struct net_device *netdev, |
4910 | struct rtnl_link_stats64 *stats) | ||
4907 | { | 4911 | { |
4908 | /* only return the current stats */ | 4912 | struct e1000_adapter *adapter = netdev_priv(netdev); |
4909 | return &netdev->stats; | 4913 | |
4914 | memset(stats, 0, sizeof(struct rtnl_link_stats64)); | ||
4915 | spin_lock(&adapter->stats64_lock); | ||
4916 | e1000e_update_stats(adapter); | ||
4917 | /* Fill out the OS statistics structure */ | ||
4918 | stats->rx_bytes = adapter->stats.gorc; | ||
4919 | stats->rx_packets = adapter->stats.gprc; | ||
4920 | stats->tx_bytes = adapter->stats.gotc; | ||
4921 | stats->tx_packets = adapter->stats.gptc; | ||
4922 | stats->multicast = adapter->stats.mprc; | ||
4923 | stats->collisions = adapter->stats.colc; | ||
4924 | |||
4925 | /* Rx Errors */ | ||
4926 | |||
4927 | /* | ||
4928 | * RLEC on some newer hardware can be incorrect so build | ||
4929 | * our own version based on RUC and ROC | ||
4930 | */ | ||
4931 | stats->rx_errors = adapter->stats.rxerrc + | ||
4932 | adapter->stats.crcerrs + adapter->stats.algnerrc + | ||
4933 | adapter->stats.ruc + adapter->stats.roc + | ||
4934 | adapter->stats.cexterr; | ||
4935 | stats->rx_length_errors = adapter->stats.ruc + | ||
4936 | adapter->stats.roc; | ||
4937 | stats->rx_crc_errors = adapter->stats.crcerrs; | ||
4938 | stats->rx_frame_errors = adapter->stats.algnerrc; | ||
4939 | stats->rx_missed_errors = adapter->stats.mpc; | ||
4940 | |||
4941 | /* Tx Errors */ | ||
4942 | stats->tx_errors = adapter->stats.ecol + | ||
4943 | adapter->stats.latecol; | ||
4944 | stats->tx_aborted_errors = adapter->stats.ecol; | ||
4945 | stats->tx_window_errors = adapter->stats.latecol; | ||
4946 | stats->tx_carrier_errors = adapter->stats.tncrs; | ||
4947 | |||
4948 | /* Tx Dropped needs to be maintained elsewhere */ | ||
4949 | |||
4950 | spin_unlock(&adapter->stats64_lock); | ||
4951 | return stats; | ||
4910 | } | 4952 | } |
4911 | 4953 | ||
4912 | /** | 4954 | /** |
@@ -5675,7 +5717,7 @@ static const struct net_device_ops e1000e_netdev_ops = { | |||
5675 | .ndo_open = e1000_open, | 5717 | .ndo_open = e1000_open, |
5676 | .ndo_stop = e1000_close, | 5718 | .ndo_stop = e1000_close, |
5677 | .ndo_start_xmit = e1000_xmit_frame, | 5719 | .ndo_start_xmit = e1000_xmit_frame, |
5678 | .ndo_get_stats = e1000_get_stats, | 5720 | .ndo_get_stats64 = e1000e_get_stats64, |
5679 | .ndo_set_multicast_list = e1000_set_multi, | 5721 | .ndo_set_multicast_list = e1000_set_multi, |
5680 | .ndo_set_mac_address = e1000_set_mac, | 5722 | .ndo_set_mac_address = e1000_set_mac, |
5681 | .ndo_change_mtu = e1000_change_mtu, | 5723 | .ndo_change_mtu = e1000_change_mtu, |