aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/intel/igc/igc_ethtool.c
diff options
context:
space:
mode:
authorSasha Neftin <sasha.neftin@intel.com>2019-02-18 03:37:31 -0500
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>2019-03-19 18:12:28 -0400
commit36b9fea60961d7426b6d4b0faaf609e5d820482d (patch)
tree169b454659327210a910669d3db3c5e4ee7bf225 /drivers/net/ethernet/intel/igc/igc_ethtool.c
parent6245c8483ae0110d2eb7e7cd2922dba1a5fce720 (diff)
igc: Add support for statistics
Add support for statistics and show basic counters. Signed-off-by: Sasha Neftin <sasha.neftin@intel.com> Tested-by: Aaron Brown <aaron.f.brown@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Diffstat (limited to 'drivers/net/ethernet/intel/igc/igc_ethtool.c')
-rw-r--r--drivers/net/ethernet/intel/igc/igc_ethtool.c233
1 files changed, 233 insertions, 0 deletions
diff --git a/drivers/net/ethernet/intel/igc/igc_ethtool.c b/drivers/net/ethernet/intel/igc/igc_ethtool.c
index 25d14fc82bf8..aaa1f97d5920 100644
--- a/drivers/net/ethernet/intel/igc/igc_ethtool.c
+++ b/drivers/net/ethernet/intel/igc/igc_ethtool.c
@@ -7,6 +7,115 @@
7 7
8#include "igc.h" 8#include "igc.h"
9 9
10/* forward declaration */
11struct igc_stats {
12 char stat_string[ETH_GSTRING_LEN];
13 int sizeof_stat;
14 int stat_offset;
15};
16
17#define IGC_STAT(_name, _stat) { \
18 .stat_string = _name, \
19 .sizeof_stat = FIELD_SIZEOF(struct igc_adapter, _stat), \
20 .stat_offset = offsetof(struct igc_adapter, _stat) \
21}
22
23static const struct igc_stats igc_gstrings_stats[] = {
24 IGC_STAT("rx_packets", stats.gprc),
25 IGC_STAT("tx_packets", stats.gptc),
26 IGC_STAT("rx_bytes", stats.gorc),
27 IGC_STAT("tx_bytes", stats.gotc),
28 IGC_STAT("rx_broadcast", stats.bprc),
29 IGC_STAT("tx_broadcast", stats.bptc),
30 IGC_STAT("rx_multicast", stats.mprc),
31 IGC_STAT("tx_multicast", stats.mptc),
32 IGC_STAT("multicast", stats.mprc),
33 IGC_STAT("collisions", stats.colc),
34 IGC_STAT("rx_crc_errors", stats.crcerrs),
35 IGC_STAT("rx_no_buffer_count", stats.rnbc),
36 IGC_STAT("rx_missed_errors", stats.mpc),
37 IGC_STAT("tx_aborted_errors", stats.ecol),
38 IGC_STAT("tx_carrier_errors", stats.tncrs),
39 IGC_STAT("tx_window_errors", stats.latecol),
40 IGC_STAT("tx_abort_late_coll", stats.latecol),
41 IGC_STAT("tx_deferred_ok", stats.dc),
42 IGC_STAT("tx_single_coll_ok", stats.scc),
43 IGC_STAT("tx_multi_coll_ok", stats.mcc),
44 IGC_STAT("tx_timeout_count", tx_timeout_count),
45 IGC_STAT("rx_long_length_errors", stats.roc),
46 IGC_STAT("rx_short_length_errors", stats.ruc),
47 IGC_STAT("rx_align_errors", stats.algnerrc),
48 IGC_STAT("tx_tcp_seg_good", stats.tsctc),
49 IGC_STAT("tx_tcp_seg_failed", stats.tsctfc),
50 IGC_STAT("rx_flow_control_xon", stats.xonrxc),
51 IGC_STAT("rx_flow_control_xoff", stats.xoffrxc),
52 IGC_STAT("tx_flow_control_xon", stats.xontxc),
53 IGC_STAT("tx_flow_control_xoff", stats.xofftxc),
54 IGC_STAT("rx_long_byte_count", stats.gorc),
55 IGC_STAT("tx_dma_out_of_sync", stats.doosync),
56 IGC_STAT("tx_smbus", stats.mgptc),
57 IGC_STAT("rx_smbus", stats.mgprc),
58 IGC_STAT("dropped_smbus", stats.mgpdc),
59 IGC_STAT("os2bmc_rx_by_bmc", stats.o2bgptc),
60 IGC_STAT("os2bmc_tx_by_bmc", stats.b2ospc),
61 IGC_STAT("os2bmc_tx_by_host", stats.o2bspc),
62 IGC_STAT("os2bmc_rx_by_host", stats.b2ogprc),
63 IGC_STAT("tx_hwtstamp_timeouts", tx_hwtstamp_timeouts),
64 IGC_STAT("tx_hwtstamp_skipped", tx_hwtstamp_skipped),
65 IGC_STAT("rx_hwtstamp_cleared", rx_hwtstamp_cleared),
66};
67
68#define IGC_NETDEV_STAT(_net_stat) { \
69 .stat_string = __stringify(_net_stat), \
70 .sizeof_stat = FIELD_SIZEOF(struct rtnl_link_stats64, _net_stat), \
71 .stat_offset = offsetof(struct rtnl_link_stats64, _net_stat) \
72}
73
74static const struct igc_stats igc_gstrings_net_stats[] = {
75 IGC_NETDEV_STAT(rx_errors),
76 IGC_NETDEV_STAT(tx_errors),
77 IGC_NETDEV_STAT(tx_dropped),
78 IGC_NETDEV_STAT(rx_length_errors),
79 IGC_NETDEV_STAT(rx_over_errors),
80 IGC_NETDEV_STAT(rx_frame_errors),
81 IGC_NETDEV_STAT(rx_fifo_errors),
82 IGC_NETDEV_STAT(tx_fifo_errors),
83 IGC_NETDEV_STAT(tx_heartbeat_errors)
84};
85
86enum igc_diagnostics_results {
87 TEST_REG = 0,
88 TEST_EEP,
89 TEST_IRQ,
90 TEST_LOOP,
91 TEST_LINK
92};
93
94static const char igc_gstrings_test[][ETH_GSTRING_LEN] = {
95 [TEST_REG] = "Register test (offline)",
96 [TEST_EEP] = "Eeprom test (offline)",
97 [TEST_IRQ] = "Interrupt test (offline)",
98 [TEST_LOOP] = "Loopback test (offline)",
99 [TEST_LINK] = "Link test (on/offline)"
100};
101
102#define IGC_TEST_LEN (sizeof(igc_gstrings_test) / ETH_GSTRING_LEN)
103
104#define IGC_GLOBAL_STATS_LEN \
105 (sizeof(igc_gstrings_stats) / sizeof(struct igc_stats))
106#define IGC_NETDEV_STATS_LEN \
107 (sizeof(igc_gstrings_net_stats) / sizeof(struct igc_stats))
108#define IGC_RX_QUEUE_STATS_LEN \
109 (sizeof(struct igc_rx_queue_stats) / sizeof(u64))
110#define IGC_TX_QUEUE_STATS_LEN 3 /* packets, bytes, restart_queue */
111#define IGC_QUEUE_STATS_LEN \
112 ((((struct igc_adapter *)netdev_priv(netdev))->num_rx_queues * \
113 IGC_RX_QUEUE_STATS_LEN) + \
114 (((struct igc_adapter *)netdev_priv(netdev))->num_tx_queues * \
115 IGC_TX_QUEUE_STATS_LEN))
116#define IGC_STATS_LEN \
117 (IGC_GLOBAL_STATS_LEN + IGC_NETDEV_STATS_LEN + IGC_QUEUE_STATS_LEN)
118
10static const char igc_priv_flags_strings[][ETH_GSTRING_LEN] = { 119static const char igc_priv_flags_strings[][ETH_GSTRING_LEN] = {
11#define IGC_PRIV_FLAGS_LEGACY_RX BIT(0) 120#define IGC_PRIV_FLAGS_LEGACY_RX BIT(0)
12 "legacy-rx", 121 "legacy-rx",
@@ -546,6 +655,127 @@ static int igc_set_pauseparam(struct net_device *netdev,
546 return retval; 655 return retval;
547} 656}
548 657
658static void igc_get_strings(struct net_device *netdev, u32 stringset, u8 *data)
659{
660 struct igc_adapter *adapter = netdev_priv(netdev);
661 u8 *p = data;
662 int i;
663
664 switch (stringset) {
665 case ETH_SS_TEST:
666 memcpy(data, *igc_gstrings_test,
667 IGC_TEST_LEN * ETH_GSTRING_LEN);
668 break;
669 case ETH_SS_STATS:
670 for (i = 0; i < IGC_GLOBAL_STATS_LEN; i++) {
671 memcpy(p, igc_gstrings_stats[i].stat_string,
672 ETH_GSTRING_LEN);
673 p += ETH_GSTRING_LEN;
674 }
675 for (i = 0; i < IGC_NETDEV_STATS_LEN; i++) {
676 memcpy(p, igc_gstrings_net_stats[i].stat_string,
677 ETH_GSTRING_LEN);
678 p += ETH_GSTRING_LEN;
679 }
680 for (i = 0; i < adapter->num_tx_queues; i++) {
681 sprintf(p, "tx_queue_%u_packets", i);
682 p += ETH_GSTRING_LEN;
683 sprintf(p, "tx_queue_%u_bytes", i);
684 p += ETH_GSTRING_LEN;
685 sprintf(p, "tx_queue_%u_restart", i);
686 p += ETH_GSTRING_LEN;
687 }
688 for (i = 0; i < adapter->num_rx_queues; i++) {
689 sprintf(p, "rx_queue_%u_packets", i);
690 p += ETH_GSTRING_LEN;
691 sprintf(p, "rx_queue_%u_bytes", i);
692 p += ETH_GSTRING_LEN;
693 sprintf(p, "rx_queue_%u_drops", i);
694 p += ETH_GSTRING_LEN;
695 sprintf(p, "rx_queue_%u_csum_err", i);
696 p += ETH_GSTRING_LEN;
697 sprintf(p, "rx_queue_%u_alloc_failed", i);
698 p += ETH_GSTRING_LEN;
699 }
700 /* BUG_ON(p - data != IGC_STATS_LEN * ETH_GSTRING_LEN); */
701 break;
702 case ETH_SS_PRIV_FLAGS:
703 memcpy(data, igc_priv_flags_strings,
704 IGC_PRIV_FLAGS_STR_LEN * ETH_GSTRING_LEN);
705 break;
706 }
707}
708
709static int igc_get_sset_count(struct net_device *netdev, int sset)
710{
711 switch (sset) {
712 case ETH_SS_STATS:
713 return IGC_STATS_LEN;
714 case ETH_SS_TEST:
715 return IGC_TEST_LEN;
716 case ETH_SS_PRIV_FLAGS:
717 return IGC_PRIV_FLAGS_STR_LEN;
718 default:
719 return -ENOTSUPP;
720 }
721}
722
723static void igc_get_ethtool_stats(struct net_device *netdev,
724 struct ethtool_stats *stats, u64 *data)
725{
726 struct igc_adapter *adapter = netdev_priv(netdev);
727 struct rtnl_link_stats64 *net_stats = &adapter->stats64;
728 unsigned int start;
729 struct igc_ring *ring;
730 int i, j;
731 char *p;
732
733 spin_lock(&adapter->stats64_lock);
734 igc_update_stats(adapter);
735
736 for (i = 0; i < IGC_GLOBAL_STATS_LEN; i++) {
737 p = (char *)adapter + igc_gstrings_stats[i].stat_offset;
738 data[i] = (igc_gstrings_stats[i].sizeof_stat ==
739 sizeof(u64)) ? *(u64 *)p : *(u32 *)p;
740 }
741 for (j = 0; j < IGC_NETDEV_STATS_LEN; j++, i++) {
742 p = (char *)net_stats + igc_gstrings_net_stats[j].stat_offset;
743 data[i] = (igc_gstrings_net_stats[j].sizeof_stat ==
744 sizeof(u64)) ? *(u64 *)p : *(u32 *)p;
745 }
746 for (j = 0; j < adapter->num_tx_queues; j++) {
747 u64 restart2;
748
749 ring = adapter->tx_ring[j];
750 do {
751 start = u64_stats_fetch_begin_irq(&ring->tx_syncp);
752 data[i] = ring->tx_stats.packets;
753 data[i + 1] = ring->tx_stats.bytes;
754 data[i + 2] = ring->tx_stats.restart_queue;
755 } while (u64_stats_fetch_retry_irq(&ring->tx_syncp, start));
756 do {
757 start = u64_stats_fetch_begin_irq(&ring->tx_syncp2);
758 restart2 = ring->tx_stats.restart_queue2;
759 } while (u64_stats_fetch_retry_irq(&ring->tx_syncp2, start));
760 data[i + 2] += restart2;
761
762 i += IGC_TX_QUEUE_STATS_LEN;
763 }
764 for (j = 0; j < adapter->num_rx_queues; j++) {
765 ring = adapter->rx_ring[j];
766 do {
767 start = u64_stats_fetch_begin_irq(&ring->rx_syncp);
768 data[i] = ring->rx_stats.packets;
769 data[i + 1] = ring->rx_stats.bytes;
770 data[i + 2] = ring->rx_stats.drops;
771 data[i + 3] = ring->rx_stats.csum_err;
772 data[i + 4] = ring->rx_stats.alloc_failed;
773 } while (u64_stats_fetch_retry_irq(&ring->rx_syncp, start));
774 i += IGC_RX_QUEUE_STATS_LEN;
775 }
776 spin_unlock(&adapter->stats64_lock);
777}
778
549static int igc_get_coalesce(struct net_device *netdev, 779static int igc_get_coalesce(struct net_device *netdev,
550 struct ethtool_coalesce *ec) 780 struct ethtool_coalesce *ec)
551{ 781{
@@ -1611,6 +1841,9 @@ static const struct ethtool_ops igc_ethtool_ops = {
1611 .set_ringparam = igc_set_ringparam, 1841 .set_ringparam = igc_set_ringparam,
1612 .get_pauseparam = igc_get_pauseparam, 1842 .get_pauseparam = igc_get_pauseparam,
1613 .set_pauseparam = igc_set_pauseparam, 1843 .set_pauseparam = igc_set_pauseparam,
1844 .get_strings = igc_get_strings,
1845 .get_sset_count = igc_get_sset_count,
1846 .get_ethtool_stats = igc_get_ethtool_stats,
1614 .get_coalesce = igc_get_coalesce, 1847 .get_coalesce = igc_get_coalesce,
1615 .set_coalesce = igc_set_coalesce, 1848 .set_coalesce = igc_set_coalesce,
1616 .get_rxnfc = igc_get_rxnfc, 1849 .get_rxnfc = igc_get_rxnfc,