Commit 37530030 authored by Maximilian Heyne's avatar Maximilian Heyne Committed by Tony Nguyen

drivers, ixgbe: export vf statistics

This change retrieves network metrics for virtual functions from the
device and exports them via the iproute2 interface.

The code for retrieving the statistics from the device is taken from the
out-of-tree driver.  The feature was introduced with version 2.0.75.7,
so the diff between this version and the previous version 2.0.72.4 was
used to identify required changes. The export via ethtool is omitted in
favor of using the standard ndo_get_vf_stats interface.

Per-VF statistics can now be printed, for instance, via

  ip --statistics link show dev eth0
Signed-off-by: default avatarMaximilian Heyne <mheyne@amazon.de>
Tested-by: default avatarKonrad Jankowski <konrad0.jankowski@intel.com>
Signed-off-by: default avatarTony Nguyen <anthony.l.nguyen@intel.com>
parent 263efe85
...@@ -167,12 +167,46 @@ enum ixgbe_tx_flags { ...@@ -167,12 +167,46 @@ enum ixgbe_tx_flags {
#define IXGBE_82599_VF_DEVICE_ID 0x10ED #define IXGBE_82599_VF_DEVICE_ID 0x10ED
#define IXGBE_X540_VF_DEVICE_ID 0x1515 #define IXGBE_X540_VF_DEVICE_ID 0x1515
#define UPDATE_VF_COUNTER_32bit(reg, last_counter, counter) \
{ \
u32 current_counter = IXGBE_READ_REG(hw, reg); \
if (current_counter < last_counter) \
counter += 0x100000000LL; \
last_counter = current_counter; \
counter &= 0xFFFFFFFF00000000LL; \
counter |= current_counter; \
}
#define UPDATE_VF_COUNTER_36bit(reg_lsb, reg_msb, last_counter, counter) \
{ \
u64 current_counter_lsb = IXGBE_READ_REG(hw, reg_lsb); \
u64 current_counter_msb = IXGBE_READ_REG(hw, reg_msb); \
u64 current_counter = (current_counter_msb << 32) | \
current_counter_lsb; \
if (current_counter < last_counter) \
counter += 0x1000000000LL; \
last_counter = current_counter; \
counter &= 0xFFFFFFF000000000LL; \
counter |= current_counter; \
}
struct vf_stats {
u64 gprc;
u64 gorc;
u64 gptc;
u64 gotc;
u64 mprc;
};
struct vf_data_storage { struct vf_data_storage {
struct pci_dev *vfdev; struct pci_dev *vfdev;
unsigned char vf_mac_addresses[ETH_ALEN]; unsigned char vf_mac_addresses[ETH_ALEN];
u16 vf_mc_hashes[IXGBE_MAX_VF_MC_ENTRIES]; u16 vf_mc_hashes[IXGBE_MAX_VF_MC_ENTRIES];
u16 num_vf_mc_hashes; u16 num_vf_mc_hashes;
bool clear_to_send; bool clear_to_send;
struct vf_stats vfstats;
struct vf_stats last_vfstats;
struct vf_stats saved_rst_vfstats;
bool pf_set_mac; bool pf_set_mac;
u16 pf_vlan; /* When set, guest VLAN config not allowed. */ u16 pf_vlan; /* When set, guest VLAN config not allowed. */
u16 pf_qos; u16 pf_qos;
......
...@@ -5549,6 +5549,47 @@ static int ixgbe_non_sfp_link_config(struct ixgbe_hw *hw) ...@@ -5549,6 +5549,47 @@ static int ixgbe_non_sfp_link_config(struct ixgbe_hw *hw)
return ret; return ret;
} }
/**
* ixgbe_clear_vf_stats_counters - Clear out VF stats after reset
* @adapter: board private structure
*
* On a reset we need to clear out the VF stats or accounting gets
* messed up because they're not clear on read.
**/
static void ixgbe_clear_vf_stats_counters(struct ixgbe_adapter *adapter)
{
struct ixgbe_hw *hw = &adapter->hw;
int i;
for (i = 0; i < adapter->num_vfs; i++) {
adapter->vfinfo[i].last_vfstats.gprc =
IXGBE_READ_REG(hw, IXGBE_PVFGPRC(i));
adapter->vfinfo[i].saved_rst_vfstats.gprc +=
adapter->vfinfo[i].vfstats.gprc;
adapter->vfinfo[i].vfstats.gprc = 0;
adapter->vfinfo[i].last_vfstats.gptc =
IXGBE_READ_REG(hw, IXGBE_PVFGPTC(i));
adapter->vfinfo[i].saved_rst_vfstats.gptc +=
adapter->vfinfo[i].vfstats.gptc;
adapter->vfinfo[i].vfstats.gptc = 0;
adapter->vfinfo[i].last_vfstats.gorc =
IXGBE_READ_REG(hw, IXGBE_PVFGORC_LSB(i));
adapter->vfinfo[i].saved_rst_vfstats.gorc +=
adapter->vfinfo[i].vfstats.gorc;
adapter->vfinfo[i].vfstats.gorc = 0;
adapter->vfinfo[i].last_vfstats.gotc =
IXGBE_READ_REG(hw, IXGBE_PVFGOTC_LSB(i));
adapter->vfinfo[i].saved_rst_vfstats.gotc +=
adapter->vfinfo[i].vfstats.gotc;
adapter->vfinfo[i].vfstats.gotc = 0;
adapter->vfinfo[i].last_vfstats.mprc =
IXGBE_READ_REG(hw, IXGBE_PVFMPRC(i));
adapter->vfinfo[i].saved_rst_vfstats.mprc +=
adapter->vfinfo[i].vfstats.mprc;
adapter->vfinfo[i].vfstats.mprc = 0;
}
}
static void ixgbe_setup_gpie(struct ixgbe_adapter *adapter) static void ixgbe_setup_gpie(struct ixgbe_adapter *adapter)
{ {
struct ixgbe_hw *hw = &adapter->hw; struct ixgbe_hw *hw = &adapter->hw;
...@@ -5684,6 +5725,7 @@ static void ixgbe_up_complete(struct ixgbe_adapter *adapter) ...@@ -5684,6 +5725,7 @@ static void ixgbe_up_complete(struct ixgbe_adapter *adapter)
adapter->link_check_timeout = jiffies; adapter->link_check_timeout = jiffies;
mod_timer(&adapter->service_timer, jiffies); mod_timer(&adapter->service_timer, jiffies);
ixgbe_clear_vf_stats_counters(adapter);
/* Set PF Reset Done bit so PF/VF Mail Ops can work */ /* Set PF Reset Done bit so PF/VF Mail Ops can work */
ctrl_ext = IXGBE_READ_REG(hw, IXGBE_CTRL_EXT); ctrl_ext = IXGBE_READ_REG(hw, IXGBE_CTRL_EXT);
ctrl_ext |= IXGBE_CTRL_EXT_PFRSTD; ctrl_ext |= IXGBE_CTRL_EXT_PFRSTD;
...@@ -7271,6 +7313,32 @@ void ixgbe_update_stats(struct ixgbe_adapter *adapter) ...@@ -7271,6 +7313,32 @@ void ixgbe_update_stats(struct ixgbe_adapter *adapter)
netdev->stats.rx_length_errors = hwstats->rlec; netdev->stats.rx_length_errors = hwstats->rlec;
netdev->stats.rx_crc_errors = hwstats->crcerrs; netdev->stats.rx_crc_errors = hwstats->crcerrs;
netdev->stats.rx_missed_errors = total_mpc; netdev->stats.rx_missed_errors = total_mpc;
/* VF Stats Collection - skip while resetting because these
* are not clear on read and otherwise you'll sometimes get
* crazy values.
*/
if (!test_bit(__IXGBE_RESETTING, &adapter->state)) {
for (i = 0; i < adapter->num_vfs; i++) {
UPDATE_VF_COUNTER_32bit(IXGBE_PVFGPRC(i),
adapter->vfinfo[i].last_vfstats.gprc,
adapter->vfinfo[i].vfstats.gprc);
UPDATE_VF_COUNTER_32bit(IXGBE_PVFGPTC(i),
adapter->vfinfo[i].last_vfstats.gptc,
adapter->vfinfo[i].vfstats.gptc);
UPDATE_VF_COUNTER_36bit(IXGBE_PVFGORC_LSB(i),
IXGBE_PVFGORC_MSB(i),
adapter->vfinfo[i].last_vfstats.gorc,
adapter->vfinfo[i].vfstats.gorc);
UPDATE_VF_COUNTER_36bit(IXGBE_PVFGOTC_LSB(i),
IXGBE_PVFGOTC_MSB(i),
adapter->vfinfo[i].last_vfstats.gotc,
adapter->vfinfo[i].vfstats.gotc);
UPDATE_VF_COUNTER_32bit(IXGBE_PVFMPRC(i),
adapter->vfinfo[i].last_vfstats.mprc,
adapter->vfinfo[i].vfstats.mprc);
}
}
} }
/** /**
...@@ -9022,6 +9090,23 @@ static void ixgbe_get_stats64(struct net_device *netdev, ...@@ -9022,6 +9090,23 @@ static void ixgbe_get_stats64(struct net_device *netdev,
stats->rx_missed_errors = netdev->stats.rx_missed_errors; stats->rx_missed_errors = netdev->stats.rx_missed_errors;
} }
static int ixgbe_ndo_get_vf_stats(struct net_device *netdev, int vf,
struct ifla_vf_stats *vf_stats)
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
if (vf < 0 || vf >= adapter->num_vfs)
return -EINVAL;
vf_stats->rx_packets = adapter->vfinfo[vf].vfstats.gprc;
vf_stats->rx_bytes = adapter->vfinfo[vf].vfstats.gorc;
vf_stats->tx_packets = adapter->vfinfo[vf].vfstats.gptc;
vf_stats->tx_bytes = adapter->vfinfo[vf].vfstats.gotc;
vf_stats->multicast = adapter->vfinfo[vf].vfstats.mprc;
return 0;
}
#ifdef CONFIG_IXGBE_DCB #ifdef CONFIG_IXGBE_DCB
/** /**
* ixgbe_validate_rtr - verify 802.1Qp to Rx packet buffer mapping is valid. * ixgbe_validate_rtr - verify 802.1Qp to Rx packet buffer mapping is valid.
...@@ -10338,6 +10423,7 @@ static const struct net_device_ops ixgbe_netdev_ops = { ...@@ -10338,6 +10423,7 @@ static const struct net_device_ops ixgbe_netdev_ops = {
.ndo_set_vf_rss_query_en = ixgbe_ndo_set_vf_rss_query_en, .ndo_set_vf_rss_query_en = ixgbe_ndo_set_vf_rss_query_en,
.ndo_set_vf_trust = ixgbe_ndo_set_vf_trust, .ndo_set_vf_trust = ixgbe_ndo_set_vf_trust,
.ndo_get_vf_config = ixgbe_ndo_get_vf_config, .ndo_get_vf_config = ixgbe_ndo_get_vf_config,
.ndo_get_vf_stats = ixgbe_ndo_get_vf_stats,
.ndo_get_stats64 = ixgbe_get_stats64, .ndo_get_stats64 = ixgbe_get_stats64,
.ndo_setup_tc = __ixgbe_setup_tc, .ndo_setup_tc = __ixgbe_setup_tc,
#ifdef IXGBE_FCOE #ifdef IXGBE_FCOE
......
...@@ -2533,6 +2533,13 @@ enum { ...@@ -2533,6 +2533,13 @@ enum {
#define IXGBE_PVFTXDCTL(P) (0x06028 + (0x40 * (P))) #define IXGBE_PVFTXDCTL(P) (0x06028 + (0x40 * (P)))
#define IXGBE_PVFTDWBAL(P) (0x06038 + (0x40 * (P))) #define IXGBE_PVFTDWBAL(P) (0x06038 + (0x40 * (P)))
#define IXGBE_PVFTDWBAH(P) (0x0603C + (0x40 * (P))) #define IXGBE_PVFTDWBAH(P) (0x0603C + (0x40 * (P)))
#define IXGBE_PVFGPRC(x) (0x0101C + (0x40 * (x)))
#define IXGBE_PVFGPTC(x) (0x08300 + (0x04 * (x)))
#define IXGBE_PVFGORC_LSB(x) (0x01020 + (0x40 * (x)))
#define IXGBE_PVFGORC_MSB(x) (0x0D020 + (0x40 * (x)))
#define IXGBE_PVFGOTC_LSB(x) (0x08400 + (0x08 * (x)))
#define IXGBE_PVFGOTC_MSB(x) (0x08404 + (0x08 * (x)))
#define IXGBE_PVFMPRC(x) (0x0D01C + (0x40 * (x)))
#define IXGBE_PVFTDWBALn(q_per_pool, vf_number, vf_q_index) \ #define IXGBE_PVFTDWBALn(q_per_pool, vf_number, vf_q_index) \
(IXGBE_PVFTDWBAL((q_per_pool)*(vf_number) + (vf_q_index))) (IXGBE_PVFTDWBAL((q_per_pool)*(vf_number) + (vf_q_index)))
......
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