i40e: convert priority flow control stats to use helpers
authorJacob Keller <jacob.e.keller@intel.com>
Tue, 31 Jul 2018 10:41:42 +0000 (03:41 -0700)
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>
Tue, 7 Aug 2018 15:19:09 +0000 (08:19 -0700)
The priority flow control statistics are laid out in the stats structure
using arrays. This made it unwieldy to use as part of an i40e_stats
array.

Add a new structure type, i40e_pfc_stats, and a helper function
i40e_get_pfc_stats which can return the stats for a given priority
value as an i40e_pfc_stats structure.

Use this to create an i40e_stats array, which we'll use to format and
copy the strings and stats into the supplied buffers.

This reduces even more boiler plate code in i40e_get_ethtool_stats and
i40e_get_stat_strings.

An alternative would be to modify the structure definition for the pfc
stats, but this is more invasive to the rest of the code base.

Note that a macro was used to setup the copy of stats from the
pf->stats, as this reduces the chance of typos in the code names. It
will produce a checkpatch.pl warning due to re-use of a macro argument.
In this case, it should be safe, as the macro will fail to compile in
cases where the argument is not a simple structure member name, and thus
arguments with side effects should not be an issue.

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/i40e/i40e_ethtool.c

index 52ccafe1d2579824e60af9f05990f481e7805447..9c380c0b02024e6513d19be2ae683c08d45b3943 100644 (file)
@@ -31,6 +31,8 @@ struct i40e_stats {
        I40E_STAT(struct i40e_vsi, _name, _stat)
 #define I40E_VEB_STAT(_name, _stat) \
        I40E_STAT(struct i40e_veb, _name, _stat)
+#define I40E_PFC_STAT(_name, _stat) \
+       I40E_STAT(struct i40e_pfc_stats, _name, _stat)
 
 static const struct i40e_stats i40e_gstrings_net_stats[] = {
        I40E_NETDEV_STAT(rx_packets),
@@ -153,6 +155,22 @@ static const struct i40e_stats i40e_gstrings_stats[] = {
        I40E_PF_STAT("port.rx_lpi_count", stats.rx_lpi_count),
 };
 
+struct i40e_pfc_stats {
+       u64 priority_xon_rx;
+       u64 priority_xoff_rx;
+       u64 priority_xon_tx;
+       u64 priority_xoff_tx;
+       u64 priority_xon_2_xoff;
+};
+
+static const struct i40e_stats i40e_gstrings_pfc_stats[] = {
+       I40E_PFC_STAT("port.tx_priority_%u_xon_tx", priority_xon_tx),
+       I40E_PFC_STAT("port.tx_priority_%u_xoff_tx", priority_xoff_tx),
+       I40E_PFC_STAT("port.rx_priority_%u_xon_rx", priority_xon_rx),
+       I40E_PFC_STAT("port.rx_priority_%u_xoff_rx", priority_xoff_rx),
+       I40E_PFC_STAT("port.rx_priority_%u_xon_2_xoff", priority_xon_2_xoff),
+};
+
 /* We use num_tx_queues here as a proxy for the maximum number of queues
  * available because we always allocate queues symmetrically.
  */
@@ -167,13 +185,9 @@ static const struct i40e_stats i40e_gstrings_stats[] = {
 #define I40E_VSI_STATS_LEN(n)  (I40E_NETDEV_STATS_LEN + \
                                 I40E_MISC_STATS_LEN + \
                                 I40E_QUEUE_STATS_LEN((n)))
-#define I40E_PFC_STATS_LEN ( \
-               (FIELD_SIZEOF(struct i40e_pf, stats.priority_xoff_rx) + \
-                FIELD_SIZEOF(struct i40e_pf, stats.priority_xon_rx) + \
-                FIELD_SIZEOF(struct i40e_pf, stats.priority_xoff_tx) + \
-                FIELD_SIZEOF(struct i40e_pf, stats.priority_xon_tx) + \
-                FIELD_SIZEOF(struct i40e_pf, stats.priority_xon_2_xoff)) \
-                / sizeof(u64))
+
+#define I40E_PFC_STATS_LEN     (ARRAY_SIZE(i40e_gstrings_pfc_stats) * \
+                                I40E_MAX_USER_PRIORITY)
 
 #define I40E_VEB_STATS_LEN     (ARRAY_SIZE(i40e_gstrings_veb_stats) + \
                                 (ARRAY_SIZE(i40e_gstrings_veb_tc_stats) * \
@@ -1798,6 +1812,31 @@ __i40e_add_ethtool_stats(u64 **data, void *pointer,
 #define i40e_add_ethtool_stats(data, pointer, stats) \
        __i40e_add_ethtool_stats(data, pointer, stats, ARRAY_SIZE(stats))
 
+/**
+ * i40e_get_pfc_stats - copy HW PFC statistics to formatted structure
+ * @pf: the PF device structure
+ * @i: the priority value to copy
+ *
+ * The PFC stats are found as arrays in pf->stats, which is not easy to pass
+ * into i40e_add_ethtool_stats. Produce a formatted i40e_pfc_stats structure
+ * of the PFC stats for the given priority.
+ **/
+static inline struct i40e_pfc_stats
+i40e_get_pfc_stats(struct i40e_pf *pf, unsigned int i)
+{
+#define I40E_GET_PFC_STAT(stat, priority) \
+       .stat = pf->stats.stat[priority]
+
+       struct i40e_pfc_stats pfc = {
+               I40E_GET_PFC_STAT(priority_xon_rx, i),
+               I40E_GET_PFC_STAT(priority_xoff_rx, i),
+               I40E_GET_PFC_STAT(priority_xon_tx, i),
+               I40E_GET_PFC_STAT(priority_xoff_tx, i),
+               I40E_GET_PFC_STAT(priority_xon_2_xoff, i),
+       };
+       return pfc;
+}
+
 /**
  * i40e_get_ethtool_stats - copy stat values into supplied buffer
  * @netdev: the netdev to collect stats for
@@ -1884,15 +1923,10 @@ static void i40e_get_ethtool_stats(struct net_device *netdev,
        i40e_add_ethtool_stats(&data, pf, i40e_gstrings_stats);
 
        for (i = 0; i < I40E_MAX_USER_PRIORITY; i++) {
-               *(data++) = pf->stats.priority_xon_tx[i];
-               *(data++) = pf->stats.priority_xoff_tx[i];
-       }
-       for (i = 0; i < I40E_MAX_USER_PRIORITY; i++) {
-               *(data++) = pf->stats.priority_xon_rx[i];
-               *(data++) = pf->stats.priority_xoff_rx[i];
+               struct i40e_pfc_stats pfc = i40e_get_pfc_stats(pf, i);
+
+               i40e_add_ethtool_stats(&data, &pfc, i40e_gstrings_pfc_stats);
        }
-       for (i = 0; i < I40E_MAX_USER_PRIORITY; i++)
-               *(data++) = pf->stats.priority_xon_2_xoff[i];
 }
 
 /**
@@ -1973,27 +2007,8 @@ static void i40e_get_stat_strings(struct net_device *netdev, u8 *data)
 
        i40e_add_stat_strings(&data, i40e_gstrings_stats);
 
-       for (i = 0; i < I40E_MAX_USER_PRIORITY; i++) {
-               snprintf(data, ETH_GSTRING_LEN,
-                        "port.tx_priority_%u_xon", i);
-               data += ETH_GSTRING_LEN;
-               snprintf(data, ETH_GSTRING_LEN,
-                        "port.tx_priority_%u_xoff", i);
-               data += ETH_GSTRING_LEN;
-       }
-       for (i = 0; i < I40E_MAX_USER_PRIORITY; i++) {
-               snprintf(data, ETH_GSTRING_LEN,
-                        "port.rx_priority_%u_xon", i);
-               data += ETH_GSTRING_LEN;
-               snprintf(data, ETH_GSTRING_LEN,
-                        "port.rx_priority_%u_xoff", i);
-               data += ETH_GSTRING_LEN;
-       }
-       for (i = 0; i < I40E_MAX_USER_PRIORITY; i++) {
-               snprintf(data, ETH_GSTRING_LEN,
-                        "port.rx_priority_%u_xon_2_xoff", i);
-               data += ETH_GSTRING_LEN;
-       }
+       for (i = 0; i < I40E_MAX_USER_PRIORITY; i++)
+               i40e_add_stat_strings(&data, i40e_gstrings_pfc_stats, i);
 
        WARN_ONCE(p - data != i40e_get_stats_count(netdev) * ETH_GSTRING_LEN,
                  "stat strings count mismatch!");