Commit 128e45eb authored by Alexander Duyck's avatar Alexander Duyck Committed by David S. Miller

igb: Rework how netdev->stats is handled

This patch does some refactoring work that I felt was needed after reviewing
the changes recently submitted relating to the replacement of net_stats with
netdev->stats.

This patch essentially creates two different collections of stats.  The
first handles the adapter specific states and is stored in gstring_stats,
and the second is for netdev specific stats and is stored in
gstring_net_stats.
Signed-off-by: default avatarAlexander Duyck <alexander.h.duyck@intel.com>
Signed-off-by: default avatarJeff Kirsher <jeffrey.t.kirsher@intel.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent a99955fc
...@@ -37,77 +37,88 @@ ...@@ -37,77 +37,88 @@
#include "igb.h" #include "igb.h"
enum {NETDEV_STATS, IGB_STATS};
struct igb_stats { struct igb_stats {
char stat_string[ETH_GSTRING_LEN]; char stat_string[ETH_GSTRING_LEN];
int type;
int sizeof_stat; int sizeof_stat;
int stat_offset; int stat_offset;
}; };
#define IGB_STAT(m) IGB_STATS, \ #define IGB_STAT(_name, _stat) { \
FIELD_SIZEOF(struct igb_adapter, m), \ .stat_string = _name, \
offsetof(struct igb_adapter, m) .sizeof_stat = FIELD_SIZEOF(struct igb_adapter, _stat), \
#define IGB_NETDEV_STAT(m) NETDEV_STATS, \ .stat_offset = offsetof(struct igb_adapter, _stat) \
FIELD_SIZEOF(struct net_device, m), \ }
offsetof(struct net_device, m)
static const struct igb_stats igb_gstrings_stats[] = { static const struct igb_stats igb_gstrings_stats[] = {
{ "rx_packets", IGB_STAT(stats.gprc) }, IGB_STAT("rx_packets", stats.gprc),
{ "tx_packets", IGB_STAT(stats.gptc) }, IGB_STAT("tx_packets", stats.gptc),
{ "rx_bytes", IGB_STAT(stats.gorc) }, IGB_STAT("rx_bytes", stats.gorc),
{ "tx_bytes", IGB_STAT(stats.gotc) }, IGB_STAT("tx_bytes", stats.gotc),
{ "rx_broadcast", IGB_STAT(stats.bprc) }, IGB_STAT("rx_broadcast", stats.bprc),
{ "tx_broadcast", IGB_STAT(stats.bptc) }, IGB_STAT("tx_broadcast", stats.bptc),
{ "rx_multicast", IGB_STAT(stats.mprc) }, IGB_STAT("rx_multicast", stats.mprc),
{ "tx_multicast", IGB_STAT(stats.mptc) }, IGB_STAT("tx_multicast", stats.mptc),
{ "rx_errors", IGB_NETDEV_STAT(stats.rx_errors) }, IGB_STAT("multicast", stats.mprc),
{ "tx_errors", IGB_NETDEV_STAT(stats.tx_errors) }, IGB_STAT("collisions", stats.colc),
{ "tx_dropped", IGB_NETDEV_STAT(stats.tx_dropped) }, IGB_STAT("rx_crc_errors", stats.crcerrs),
{ "multicast", IGB_STAT(stats.mprc) }, IGB_STAT("rx_no_buffer_count", stats.rnbc),
{ "collisions", IGB_STAT(stats.colc) }, IGB_STAT("rx_missed_errors", stats.mpc),
{ "rx_length_errors", IGB_NETDEV_STAT(stats.rx_length_errors) }, IGB_STAT("tx_aborted_errors", stats.ecol),
{ "rx_over_errors", IGB_NETDEV_STAT(stats.rx_over_errors) }, IGB_STAT("tx_carrier_errors", stats.tncrs),
{ "rx_crc_errors", IGB_STAT(stats.crcerrs) }, IGB_STAT("tx_window_errors", stats.latecol),
{ "rx_frame_errors", IGB_NETDEV_STAT(stats.rx_frame_errors) }, IGB_STAT("tx_abort_late_coll", stats.latecol),
{ "rx_no_buffer_count", IGB_STAT(stats.rnbc) }, IGB_STAT("tx_deferred_ok", stats.dc),
{ "rx_queue_drop_packet_count", IGB_NETDEV_STAT(stats.rx_fifo_errors) }, IGB_STAT("tx_single_coll_ok", stats.scc),
{ "rx_missed_errors", IGB_STAT(stats.mpc) }, IGB_STAT("tx_multi_coll_ok", stats.mcc),
{ "tx_aborted_errors", IGB_STAT(stats.ecol) }, IGB_STAT("tx_timeout_count", tx_timeout_count),
{ "tx_carrier_errors", IGB_STAT(stats.tncrs) }, IGB_STAT("rx_long_length_errors", stats.roc),
{ "tx_fifo_errors", IGB_NETDEV_STAT(stats.tx_fifo_errors) }, IGB_STAT("rx_short_length_errors", stats.ruc),
{ "tx_heartbeat_errors", IGB_NETDEV_STAT(stats.tx_heartbeat_errors) }, IGB_STAT("rx_align_errors", stats.algnerrc),
{ "tx_window_errors", IGB_STAT(stats.latecol) }, IGB_STAT("tx_tcp_seg_good", stats.tsctc),
{ "tx_abort_late_coll", IGB_STAT(stats.latecol) }, IGB_STAT("tx_tcp_seg_failed", stats.tsctfc),
{ "tx_deferred_ok", IGB_STAT(stats.dc) }, IGB_STAT("rx_flow_control_xon", stats.xonrxc),
{ "tx_single_coll_ok", IGB_STAT(stats.scc) }, IGB_STAT("rx_flow_control_xoff", stats.xoffrxc),
{ "tx_multi_coll_ok", IGB_STAT(stats.mcc) }, IGB_STAT("tx_flow_control_xon", stats.xontxc),
{ "tx_timeout_count", IGB_STAT(tx_timeout_count) }, IGB_STAT("tx_flow_control_xoff", stats.xofftxc),
{ "rx_long_length_errors", IGB_STAT(stats.roc) }, IGB_STAT("rx_long_byte_count", stats.gorc),
{ "rx_short_length_errors", IGB_STAT(stats.ruc) }, IGB_STAT("tx_dma_out_of_sync", stats.doosync),
{ "rx_align_errors", IGB_STAT(stats.algnerrc) }, IGB_STAT("tx_smbus", stats.mgptc),
{ "tx_tcp_seg_good", IGB_STAT(stats.tsctc) }, IGB_STAT("rx_smbus", stats.mgprc),
{ "tx_tcp_seg_failed", IGB_STAT(stats.tsctfc) }, IGB_STAT("dropped_smbus", stats.mgpdc),
{ "rx_flow_control_xon", IGB_STAT(stats.xonrxc) }, };
{ "rx_flow_control_xoff", IGB_STAT(stats.xoffrxc) },
{ "tx_flow_control_xon", IGB_STAT(stats.xontxc) }, #define IGB_NETDEV_STAT(_net_stat) { \
{ "tx_flow_control_xoff", IGB_STAT(stats.xofftxc) }, .stat_string = __stringify(_net_stat), \
{ "rx_long_byte_count", IGB_STAT(stats.gorc) }, .sizeof_stat = FIELD_SIZEOF(struct net_device_stats, _net_stat), \
{ "tx_dma_out_of_sync", IGB_STAT(stats.doosync) }, .stat_offset = offsetof(struct net_device_stats, _net_stat) \
{ "tx_smbus", IGB_STAT(stats.mgptc) }, }
{ "rx_smbus", IGB_STAT(stats.mgprc) }, static const struct igb_stats igb_gstrings_net_stats[] = {
{ "dropped_smbus", IGB_STAT(stats.mgpdc) }, IGB_NETDEV_STAT(rx_errors),
IGB_NETDEV_STAT(tx_errors),
IGB_NETDEV_STAT(tx_dropped),
IGB_NETDEV_STAT(rx_length_errors),
IGB_NETDEV_STAT(rx_over_errors),
IGB_NETDEV_STAT(rx_frame_errors),
IGB_NETDEV_STAT(rx_fifo_errors),
IGB_NETDEV_STAT(tx_fifo_errors),
IGB_NETDEV_STAT(tx_heartbeat_errors)
}; };
#define IGB_GLOBAL_STATS_LEN \
(sizeof(igb_gstrings_stats) / sizeof(struct igb_stats))
#define IGB_NETDEV_STATS_LEN \
(sizeof(igb_gstrings_net_stats) / sizeof(struct igb_stats))
#define IGB_RX_QUEUE_STATS_LEN \
(sizeof(struct igb_rx_queue_stats) / sizeof(u64))
#define IGB_TX_QUEUE_STATS_LEN \
(sizeof(struct igb_tx_queue_stats) / sizeof(u64))
#define IGB_QUEUE_STATS_LEN \ #define IGB_QUEUE_STATS_LEN \
((((struct igb_adapter *)netdev_priv(netdev))->num_rx_queues * \ ((((struct igb_adapter *)netdev_priv(netdev))->num_rx_queues * \
(sizeof(struct igb_rx_queue_stats) / sizeof(u64))) + \ IGB_RX_QUEUE_STATS_LEN) + \
(((struct igb_adapter *)netdev_priv(netdev))->num_tx_queues * \ (((struct igb_adapter *)netdev_priv(netdev))->num_tx_queues * \
(sizeof(struct igb_tx_queue_stats) / sizeof(u64)))) IGB_TX_QUEUE_STATS_LEN))
#define IGB_GLOBAL_STATS_LEN \ #define IGB_STATS_LEN \
(sizeof(igb_gstrings_stats) / sizeof(struct igb_stats)) (IGB_GLOBAL_STATS_LEN + IGB_NETDEV_STATS_LEN + IGB_QUEUE_STATS_LEN)
#define IGB_STATS_LEN (IGB_GLOBAL_STATS_LEN + IGB_QUEUE_STATS_LEN)
static const char igb_gstrings_test[][ETH_GSTRING_LEN] = { static const char igb_gstrings_test[][ETH_GSTRING_LEN] = {
"Register test (offline)", "Eeprom test (offline)", "Register test (offline)", "Eeprom test (offline)",
"Interrupt test (offline)", "Loopback test (offline)", "Interrupt test (offline)", "Loopback test (offline)",
...@@ -1922,43 +1933,32 @@ static void igb_get_ethtool_stats(struct net_device *netdev, ...@@ -1922,43 +1933,32 @@ static void igb_get_ethtool_stats(struct net_device *netdev,
struct ethtool_stats *stats, u64 *data) struct ethtool_stats *stats, u64 *data)
{ {
struct igb_adapter *adapter = netdev_priv(netdev); struct igb_adapter *adapter = netdev_priv(netdev);
struct net_device_stats *net_stats = &netdev->stats;
u64 *queue_stat; u64 *queue_stat;
int stat_count_tx = sizeof(struct igb_tx_queue_stats) / sizeof(u64); int i, j, k;
int stat_count_rx = sizeof(struct igb_rx_queue_stats) / sizeof(u64); char *p;
int j;
int i;
char *p = NULL;
igb_update_stats(adapter); igb_update_stats(adapter);
for (i = 0; i < IGB_GLOBAL_STATS_LEN; i++) { for (i = 0; i < IGB_GLOBAL_STATS_LEN; i++) {
switch (igb_gstrings_stats[i].type) { p = (char *)adapter + igb_gstrings_stats[i].stat_offset;
case NETDEV_STATS:
p = (char *) netdev +
igb_gstrings_stats[i].stat_offset;
break;
case IGB_STATS:
p = (char *) adapter +
igb_gstrings_stats[i].stat_offset;
break;
}
data[i] = (igb_gstrings_stats[i].sizeof_stat == data[i] = (igb_gstrings_stats[i].sizeof_stat ==
sizeof(u64)) ? *(u64 *)p : *(u32 *)p; sizeof(u64)) ? *(u64 *)p : *(u32 *)p;
} }
for (j = 0; j < IGB_NETDEV_STATS_LEN; j++, i++) {
p = (char *)net_stats + igb_gstrings_net_stats[j].stat_offset;
data[i] = (igb_gstrings_net_stats[j].sizeof_stat ==
sizeof(u64)) ? *(u64 *)p : *(u32 *)p;
}
for (j = 0; j < adapter->num_tx_queues; j++) { for (j = 0; j < adapter->num_tx_queues; j++) {
int k;
queue_stat = (u64 *)&adapter->tx_ring[j].tx_stats; queue_stat = (u64 *)&adapter->tx_ring[j].tx_stats;
for (k = 0; k < stat_count_tx; k++) for (k = 0; k < IGB_TX_QUEUE_STATS_LEN; k++, i++)
data[i + k] = queue_stat[k]; data[i] = queue_stat[k];
i += k;
} }
for (j = 0; j < adapter->num_rx_queues; j++) { for (j = 0; j < adapter->num_rx_queues; j++) {
int k;
queue_stat = (u64 *)&adapter->rx_ring[j].rx_stats; queue_stat = (u64 *)&adapter->rx_ring[j].rx_stats;
for (k = 0; k < stat_count_rx; k++) for (k = 0; k < IGB_RX_QUEUE_STATS_LEN; k++, i++)
data[i + k] = queue_stat[k]; data[i] = queue_stat[k];
i += k;
} }
} }
...@@ -1979,6 +1979,11 @@ static void igb_get_strings(struct net_device *netdev, u32 stringset, u8 *data) ...@@ -1979,6 +1979,11 @@ static void igb_get_strings(struct net_device *netdev, u32 stringset, u8 *data)
ETH_GSTRING_LEN); ETH_GSTRING_LEN);
p += ETH_GSTRING_LEN; p += ETH_GSTRING_LEN;
} }
for (i = 0; i < IGB_NETDEV_STATS_LEN; i++) {
memcpy(p, igb_gstrings_net_stats[i].stat_string,
ETH_GSTRING_LEN);
p += ETH_GSTRING_LEN;
}
for (i = 0; i < adapter->num_tx_queues; i++) { for (i = 0; i < adapter->num_tx_queues; i++) {
sprintf(p, "tx_queue_%u_packets", i); sprintf(p, "tx_queue_%u_packets", i);
p += ETH_GSTRING_LEN; p += ETH_GSTRING_LEN;
......
...@@ -3789,7 +3789,7 @@ static int igb_change_mtu(struct net_device *netdev, int new_mtu) ...@@ -3789,7 +3789,7 @@ static int igb_change_mtu(struct net_device *netdev, int new_mtu)
void igb_update_stats(struct igb_adapter *adapter) void igb_update_stats(struct igb_adapter *adapter)
{ {
struct net_device *netdev = adapter->netdev; struct net_device_stats *net_stats = igb_get_stats(adapter->netdev);
struct e1000_hw *hw = &adapter->hw; struct e1000_hw *hw = &adapter->hw;
struct pci_dev *pdev = adapter->pdev; struct pci_dev *pdev = adapter->pdev;
u32 rnbc; u32 rnbc;
...@@ -3813,13 +3813,13 @@ void igb_update_stats(struct igb_adapter *adapter) ...@@ -3813,13 +3813,13 @@ void igb_update_stats(struct igb_adapter *adapter)
for (i = 0; i < adapter->num_rx_queues; i++) { for (i = 0; i < adapter->num_rx_queues; i++) {
u32 rqdpc_tmp = rd32(E1000_RQDPC(i)) & 0x0FFF; u32 rqdpc_tmp = rd32(E1000_RQDPC(i)) & 0x0FFF;
adapter->rx_ring[i].rx_stats.drops += rqdpc_tmp; adapter->rx_ring[i].rx_stats.drops += rqdpc_tmp;
netdev->stats.rx_fifo_errors += rqdpc_tmp; net_stats->rx_fifo_errors += rqdpc_tmp;
bytes += adapter->rx_ring[i].rx_stats.bytes; bytes += adapter->rx_ring[i].rx_stats.bytes;
packets += adapter->rx_ring[i].rx_stats.packets; packets += adapter->rx_ring[i].rx_stats.packets;
} }
netdev->stats.rx_bytes = bytes; net_stats->rx_bytes = bytes;
netdev->stats.rx_packets = packets; net_stats->rx_packets = packets;
bytes = 0; bytes = 0;
packets = 0; packets = 0;
...@@ -3827,8 +3827,8 @@ void igb_update_stats(struct igb_adapter *adapter) ...@@ -3827,8 +3827,8 @@ void igb_update_stats(struct igb_adapter *adapter)
bytes += adapter->tx_ring[i].tx_stats.bytes; bytes += adapter->tx_ring[i].tx_stats.bytes;
packets += adapter->tx_ring[i].tx_stats.packets; packets += adapter->tx_ring[i].tx_stats.packets;
} }
netdev->stats.tx_bytes = bytes; net_stats->tx_bytes = bytes;
netdev->stats.tx_packets = packets; net_stats->tx_packets = packets;
/* read stats registers */ /* read stats registers */
adapter->stats.crcerrs += rd32(E1000_CRCERRS); adapter->stats.crcerrs += rd32(E1000_CRCERRS);
...@@ -3865,7 +3865,7 @@ void igb_update_stats(struct igb_adapter *adapter) ...@@ -3865,7 +3865,7 @@ void igb_update_stats(struct igb_adapter *adapter)
rd32(E1000_GOTCH); /* clear GOTCL */ rd32(E1000_GOTCH); /* clear GOTCL */
rnbc = rd32(E1000_RNBC); rnbc = rd32(E1000_RNBC);
adapter->stats.rnbc += rnbc; adapter->stats.rnbc += rnbc;
netdev->stats.rx_fifo_errors += rnbc; net_stats->rx_fifo_errors += rnbc;
adapter->stats.ruc += rd32(E1000_RUC); adapter->stats.ruc += rd32(E1000_RUC);
adapter->stats.rfc += rd32(E1000_RFC); adapter->stats.rfc += rd32(E1000_RFC);
adapter->stats.rjc += rd32(E1000_RJC); adapter->stats.rjc += rd32(E1000_RJC);
...@@ -3906,29 +3906,29 @@ void igb_update_stats(struct igb_adapter *adapter) ...@@ -3906,29 +3906,29 @@ void igb_update_stats(struct igb_adapter *adapter)
adapter->stats.icrxdmtc += rd32(E1000_ICRXDMTC); adapter->stats.icrxdmtc += rd32(E1000_ICRXDMTC);
/* Fill out the OS statistics structure */ /* Fill out the OS statistics structure */
netdev->stats.multicast = adapter->stats.mprc; net_stats->multicast = adapter->stats.mprc;
netdev->stats.collisions = adapter->stats.colc; net_stats->collisions = adapter->stats.colc;
/* Rx Errors */ /* Rx Errors */
/* RLEC on some newer hardware can be incorrect so build /* RLEC on some newer hardware can be incorrect so build
* our own version based on RUC and ROC */ * our own version based on RUC and ROC */
netdev->stats.rx_errors = adapter->stats.rxerrc + net_stats->rx_errors = adapter->stats.rxerrc +
adapter->stats.crcerrs + adapter->stats.algnerrc + adapter->stats.crcerrs + adapter->stats.algnerrc +
adapter->stats.ruc + adapter->stats.roc + adapter->stats.ruc + adapter->stats.roc +
adapter->stats.cexterr; adapter->stats.cexterr;
netdev->stats.rx_length_errors = adapter->stats.ruc + net_stats->rx_length_errors = adapter->stats.ruc +
adapter->stats.roc; adapter->stats.roc;
netdev->stats.rx_crc_errors = adapter->stats.crcerrs; net_stats->rx_crc_errors = adapter->stats.crcerrs;
netdev->stats.rx_frame_errors = adapter->stats.algnerrc; net_stats->rx_frame_errors = adapter->stats.algnerrc;
netdev->stats.rx_missed_errors = adapter->stats.mpc; net_stats->rx_missed_errors = adapter->stats.mpc;
/* Tx Errors */ /* Tx Errors */
netdev->stats.tx_errors = adapter->stats.ecol + net_stats->tx_errors = adapter->stats.ecol +
adapter->stats.latecol; adapter->stats.latecol;
netdev->stats.tx_aborted_errors = adapter->stats.ecol; net_stats->tx_aborted_errors = adapter->stats.ecol;
netdev->stats.tx_window_errors = adapter->stats.latecol; net_stats->tx_window_errors = adapter->stats.latecol;
netdev->stats.tx_carrier_errors = adapter->stats.tncrs; net_stats->tx_carrier_errors = adapter->stats.tncrs;
/* Tx Dropped needs to be maintained elsewhere */ /* Tx Dropped needs to be maintained elsewhere */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment