bnxt_en: Add ethtool -S priority counters.
authorMichael Chan <michael.chan@broadcom.com>
Sun, 16 Dec 2018 23:46:26 +0000 (18:46 -0500)
committerDavid S. Miller <davem@davemloft.net>
Tue, 18 Dec 2018 07:08:53 +0000 (23:08 -0800)
Display the CoS counters as additional priority counters by looking up
the priority to CoS queue mapping.  If the TX extended port statistics
block size returned by firmware is big enough to cover the CoS counters,
then we will display the new priority counters.  We call firmware to get
the up-to-date pri2cos mapping to convert the CoS counters to
priority counters.

Signed-off-by: Michael Chan <michael.chan@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/broadcom/bnxt/bnxt.c
drivers/net/ethernet/broadcom/bnxt/bnxt.h
drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c

index 6f407a6f9432f75c10988146c4a2c5bbc575aa1a..a57f4409153bd6df350af62f09216bc982c21a7a 100644 (file)
@@ -6511,6 +6511,7 @@ static int bnxt_hwrm_port_qstats(struct bnxt *bp)
 static int bnxt_hwrm_port_qstats_ext(struct bnxt *bp)
 {
        struct hwrm_port_qstats_ext_output *resp = bp->hwrm_cmd_resp_addr;
+       struct hwrm_queue_pri2cos_qcfg_input req2 = {0};
        struct hwrm_port_qstats_ext_input req = {0};
        struct bnxt_pf_info *pf = &bp->pf;
        int rc;
@@ -6533,6 +6534,34 @@ static int bnxt_hwrm_port_qstats_ext(struct bnxt *bp)
                bp->fw_rx_stats_ext_size = 0;
                bp->fw_tx_stats_ext_size = 0;
        }
+       if (bp->fw_tx_stats_ext_size <=
+           offsetof(struct tx_port_stats_ext, pfc_pri0_tx_duration_us) / 8) {
+               mutex_unlock(&bp->hwrm_cmd_lock);
+               bp->pri2cos_valid = 0;
+               return rc;
+       }
+
+       bnxt_hwrm_cmd_hdr_init(bp, &req2, HWRM_QUEUE_PRI2COS_QCFG, -1, -1);
+       req2.flags = cpu_to_le32(QUEUE_PRI2COS_QCFG_REQ_FLAGS_IVLAN);
+
+       rc = _hwrm_send_message(bp, &req2, sizeof(req2), HWRM_CMD_TIMEOUT);
+       if (!rc) {
+               struct hwrm_queue_pri2cos_qcfg_output *resp2;
+               u8 *pri2cos;
+               int i, j;
+
+               resp2 = bp->hwrm_cmd_resp_addr;
+               pri2cos = &resp2->pri0_cos_queue_id;
+               for (i = 0; i < 8; i++) {
+                       u8 queue_id = pri2cos[i];
+
+                       for (j = 0; j < bp->max_q; j++) {
+                               if (bp->q_ids[j] == queue_id)
+                                       bp->pri2cos[i] = j;
+                       }
+               }
+               bp->pri2cos_valid = 1;
+       }
        mutex_unlock(&bp->hwrm_cmd_lock);
        return rc;
 }
index fdc600cd5da7be7c53074b0a21787874ba3a68b0..3c6a39d99f1ff674fa39c635c9f9dc886807b0ed 100644 (file)
@@ -1483,6 +1483,8 @@ struct bnxt {
        int                     hw_port_stats_size;
        u16                     fw_rx_stats_ext_size;
        u16                     fw_tx_stats_ext_size;
+       u8                      pri2cos[8];
+       u8                      pri2cos_valid;
 
        u16                     hwrm_max_req_len;
        u16                     hwrm_max_ext_req_len;
index 5a746aed7f3c0fc748bd7a4b103c2488f08e8f96..475b4792c7bb01523fd89a566f1c113b762059dc 100644 (file)
@@ -207,6 +207,34 @@ reset_coalesce:
        BNXT_TX_STATS_EXT_COS_ENTRY(6),                         \
        BNXT_TX_STATS_EXT_COS_ENTRY(7)                          \
 
+#define BNXT_RX_STATS_PRI_ENTRY(counter, n)            \
+       { BNXT_RX_STATS_EXT_OFFSET(counter##_cos0),     \
+         __stringify(counter##_pri##n) }
+
+#define BNXT_TX_STATS_PRI_ENTRY(counter, n)            \
+       { BNXT_TX_STATS_EXT_OFFSET(counter##_cos0),     \
+         __stringify(counter##_pri##n) }
+
+#define BNXT_RX_STATS_PRI_ENTRIES(counter)             \
+       BNXT_RX_STATS_PRI_ENTRY(counter, 0),            \
+       BNXT_RX_STATS_PRI_ENTRY(counter, 1),            \
+       BNXT_RX_STATS_PRI_ENTRY(counter, 2),            \
+       BNXT_RX_STATS_PRI_ENTRY(counter, 3),            \
+       BNXT_RX_STATS_PRI_ENTRY(counter, 4),            \
+       BNXT_RX_STATS_PRI_ENTRY(counter, 5),            \
+       BNXT_RX_STATS_PRI_ENTRY(counter, 6),            \
+       BNXT_RX_STATS_PRI_ENTRY(counter, 7)
+
+#define BNXT_TX_STATS_PRI_ENTRIES(counter)             \
+       BNXT_TX_STATS_PRI_ENTRY(counter, 0),            \
+       BNXT_TX_STATS_PRI_ENTRY(counter, 1),            \
+       BNXT_TX_STATS_PRI_ENTRY(counter, 2),            \
+       BNXT_TX_STATS_PRI_ENTRY(counter, 3),            \
+       BNXT_TX_STATS_PRI_ENTRY(counter, 4),            \
+       BNXT_TX_STATS_PRI_ENTRY(counter, 5),            \
+       BNXT_TX_STATS_PRI_ENTRY(counter, 6),            \
+       BNXT_TX_STATS_PRI_ENTRY(counter, 7)
+
 enum {
        RX_TOTAL_DISCARDS,
        TX_TOTAL_DISCARDS,
@@ -327,8 +355,41 @@ static const struct {
        BNXT_TX_STATS_EXT_PFC_ENTRIES,
 };
 
+static const struct {
+       long base_off;
+       char string[ETH_GSTRING_LEN];
+} bnxt_rx_bytes_pri_arr[] = {
+       BNXT_RX_STATS_PRI_ENTRIES(rx_bytes),
+};
+
+static const struct {
+       long base_off;
+       char string[ETH_GSTRING_LEN];
+} bnxt_rx_pkts_pri_arr[] = {
+       BNXT_RX_STATS_PRI_ENTRIES(rx_packets),
+};
+
+static const struct {
+       long base_off;
+       char string[ETH_GSTRING_LEN];
+} bnxt_tx_bytes_pri_arr[] = {
+       BNXT_TX_STATS_PRI_ENTRIES(tx_bytes),
+};
+
+static const struct {
+       long base_off;
+       char string[ETH_GSTRING_LEN];
+} bnxt_tx_pkts_pri_arr[] = {
+       BNXT_TX_STATS_PRI_ENTRIES(tx_packets),
+};
+
 #define BNXT_NUM_SW_FUNC_STATS ARRAY_SIZE(bnxt_sw_func_stats)
 #define BNXT_NUM_PORT_STATS ARRAY_SIZE(bnxt_port_stats_arr)
+#define BNXT_NUM_STATS_PRI                     \
+       (ARRAY_SIZE(bnxt_rx_bytes_pri_arr) +    \
+        ARRAY_SIZE(bnxt_rx_pkts_pri_arr) +     \
+        ARRAY_SIZE(bnxt_tx_bytes_pri_arr) +    \
+        ARRAY_SIZE(bnxt_tx_pkts_pri_arr))
 
 static int bnxt_get_num_stats(struct bnxt *bp)
 {
@@ -339,9 +400,12 @@ static int bnxt_get_num_stats(struct bnxt *bp)
        if (bp->flags & BNXT_FLAG_PORT_STATS)
                num_stats += BNXT_NUM_PORT_STATS;
 
-       if (bp->flags & BNXT_FLAG_PORT_STATS_EXT)
+       if (bp->flags & BNXT_FLAG_PORT_STATS_EXT) {
                num_stats += bp->fw_rx_stats_ext_size +
                             bp->fw_tx_stats_ext_size;
+               if (bp->pri2cos_valid)
+                       num_stats += BNXT_NUM_STATS_PRI;
+       }
 
        return num_stats;
 }
@@ -415,6 +479,32 @@ static void bnxt_get_ethtool_stats(struct net_device *dev,
                        buf[j] = le64_to_cpu(*(tx_port_stats_ext +
                                        bnxt_tx_port_stats_ext_arr[i].offset));
                }
+               if (bp->pri2cos_valid) {
+                       for (i = 0; i < 8; i++, j++) {
+                               long n = bnxt_rx_bytes_pri_arr[i].base_off +
+                                        bp->pri2cos[i];
+
+                               buf[j] = le64_to_cpu(*(rx_port_stats_ext + n));
+                       }
+                       for (i = 0; i < 8; i++, j++) {
+                               long n = bnxt_rx_pkts_pri_arr[i].base_off +
+                                        bp->pri2cos[i];
+
+                               buf[j] = le64_to_cpu(*(rx_port_stats_ext + n));
+                       }
+                       for (i = 0; i < 8; i++, j++) {
+                               long n = bnxt_tx_bytes_pri_arr[i].base_off +
+                                        bp->pri2cos[i];
+
+                               buf[j] = le64_to_cpu(*(tx_port_stats_ext + n));
+                       }
+                       for (i = 0; i < 8; i++, j++) {
+                               long n = bnxt_tx_pkts_pri_arr[i].base_off +
+                                        bp->pri2cos[i];
+
+                               buf[j] = le64_to_cpu(*(tx_port_stats_ext + n));
+                       }
+               }
        }
 }
 
@@ -493,6 +583,28 @@ static void bnxt_get_strings(struct net_device *dev, u32 stringset, u8 *buf)
                                       bnxt_tx_port_stats_ext_arr[i].string);
                                buf += ETH_GSTRING_LEN;
                        }
+                       if (bp->pri2cos_valid) {
+                               for (i = 0; i < 8; i++) {
+                                       strcpy(buf,
+                                              bnxt_rx_bytes_pri_arr[i].string);
+                                       buf += ETH_GSTRING_LEN;
+                               }
+                               for (i = 0; i < 8; i++) {
+                                       strcpy(buf,
+                                              bnxt_rx_pkts_pri_arr[i].string);
+                                       buf += ETH_GSTRING_LEN;
+                               }
+                               for (i = 0; i < 8; i++) {
+                                       strcpy(buf,
+                                              bnxt_tx_bytes_pri_arr[i].string);
+                                       buf += ETH_GSTRING_LEN;
+                               }
+                               for (i = 0; i < 8; i++) {
+                                       strcpy(buf,
+                                              bnxt_tx_pkts_pri_arr[i].string);
+                                       buf += ETH_GSTRING_LEN;
+                               }
+                       }
                }
                break;
        case ETH_SS_TEST: