fm10k: add support for ndo_get_vf_stats operation
authorJacob Keller <jacob.e.keller@intel.com>
Tue, 20 Aug 2019 21:19:21 +0000 (14:19 -0700)
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>
Mon, 4 Nov 2019 21:12:14 +0000 (13:12 -0800)
Support capturing and reporting statistics for all of the VFs associated
with a given PF device via the ndo_get_vf_stats callback.

Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
drivers/net/ethernet/intel/fm10k/fm10k.h
drivers/net/ethernet/intel/fm10k/fm10k_iov.c
drivers/net/ethernet/intel/fm10k/fm10k_netdev.c
drivers/net/ethernet/intel/fm10k/fm10k_pci.c
drivers/net/ethernet/intel/fm10k/fm10k_type.h

index b144419..f306084 100644 (file)
@@ -534,6 +534,7 @@ void fm10k_iov_suspend(struct pci_dev *pdev);
 int fm10k_iov_resume(struct pci_dev *pdev);
 void fm10k_iov_disable(struct pci_dev *pdev);
 int fm10k_iov_configure(struct pci_dev *pdev, int num_vfs);
+void fm10k_iov_update_stats(struct fm10k_intfc *interface);
 s32 fm10k_iov_update_pvid(struct fm10k_intfc *interface, u16 glort, u16 pvid);
 int fm10k_ndo_set_vf_mac(struct net_device *netdev, int vf_idx, u8 *mac);
 int fm10k_ndo_set_vf_vlan(struct net_device *netdev,
@@ -542,6 +543,8 @@ int fm10k_ndo_set_vf_bw(struct net_device *netdev, int vf_idx,
                        int __always_unused min_rate, int max_rate);
 int fm10k_ndo_get_vf_config(struct net_device *netdev,
                            int vf_idx, struct ifla_vf_info *ivi);
+int fm10k_ndo_get_vf_stats(struct net_device *netdev,
+                          int vf_idx, struct ifla_vf_stats *stats);
 
 /* DebugFS */
 #ifdef CONFIG_DEBUG_FS
index afe1faf..8c50a12 100644 (file)
@@ -520,6 +520,27 @@ int fm10k_iov_configure(struct pci_dev *pdev, int num_vfs)
        return num_vfs;
 }
 
+/**
+ * fm10k_iov_update_stats - Update stats for all VFs
+ * @interface: device private structure
+ *
+ * Updates the VF statistics for all enabled VFs. Expects to be called by
+ * fm10k_update_stats and assumes that locking via the __FM10K_UPDATING_STATS
+ * bit is already handled.
+ */
+void fm10k_iov_update_stats(struct fm10k_intfc *interface)
+{
+       struct fm10k_iov_data *iov_data = interface->iov_data;
+       struct fm10k_hw *hw = &interface->hw;
+       int i;
+
+       if (!iov_data)
+               return;
+
+       for (i = 0; i < iov_data->num_vfs; i++)
+               hw->iov.ops.update_stats(hw, iov_data->vf_info[i].stats, i);
+}
+
 static inline void fm10k_reset_vf_info(struct fm10k_intfc *interface,
                                       struct fm10k_vf_info *vf_info)
 {
@@ -650,3 +671,30 @@ int fm10k_ndo_get_vf_config(struct net_device *netdev,
 
        return 0;
 }
+
+int fm10k_ndo_get_vf_stats(struct net_device *netdev,
+                          int vf_idx, struct ifla_vf_stats *stats)
+{
+       struct fm10k_intfc *interface = netdev_priv(netdev);
+       struct fm10k_iov_data *iov_data = interface->iov_data;
+       struct fm10k_hw *hw = &interface->hw;
+       struct fm10k_hw_stats_q *hw_stats;
+       u32 idx, qpp;
+
+       /* verify SR-IOV is active and that vf idx is valid */
+       if (!iov_data || vf_idx >= iov_data->num_vfs)
+               return -EINVAL;
+
+       qpp = fm10k_queues_per_pool(hw);
+       hw_stats = iov_data->vf_info[vf_idx].stats;
+
+       for (idx = 0; idx < qpp; idx++) {
+               stats->rx_packets += hw_stats[idx].rx_packets.count;
+               stats->tx_packets += hw_stats[idx].tx_packets.count;
+               stats->rx_bytes += hw_stats[idx].rx_bytes.count;
+               stats->tx_bytes += hw_stats[idx].tx_bytes.count;
+               stats->rx_dropped += hw_stats[idx].rx_drops.count;
+       }
+
+       return 0;
+}
index 09f7a24..68baee0 100644 (file)
@@ -1643,6 +1643,7 @@ static const struct net_device_ops fm10k_netdev_ops = {
        .ndo_set_vf_vlan        = fm10k_ndo_set_vf_vlan,
        .ndo_set_vf_rate        = fm10k_ndo_set_vf_bw,
        .ndo_get_vf_config      = fm10k_ndo_get_vf_config,
+       .ndo_get_vf_stats       = fm10k_ndo_get_vf_stats,
        .ndo_udp_tunnel_add     = fm10k_udp_tunnel_add,
        .ndo_udp_tunnel_del     = fm10k_udp_tunnel_del,
        .ndo_dfwd_add_station   = fm10k_dfwd_add_station,
index bb236fa..d122d00 100644 (file)
@@ -630,6 +630,9 @@ void fm10k_update_stats(struct fm10k_intfc *interface)
        net_stats->rx_errors = rx_errors;
        net_stats->rx_dropped = interface->stats.nodesc_drop.count;
 
+       /* Update VF statistics */
+       fm10k_iov_update_stats(interface);
+
        clear_bit(__FM10K_UPDATING_STATS, interface->state);
 }
 
index 15ac1c7..63968c5 100644 (file)
@@ -581,6 +581,7 @@ struct fm10k_vf_info {
         * at the same offset as the mailbox
         */
        struct fm10k_mbx_info   mbx;            /* PF side of VF mailbox */
+       struct fm10k_hw_stats_q stats[FM10K_MAX_QUEUES_POOL];
        int                     rate;           /* Tx BW cap as defined by OS */
        u16                     glort;          /* resource tag for this VF */
        u16                     sw_vid;         /* Switch API assigned VLAN */