bnxt_en: Add support for PCIe statistics
authorVasundhara Volam <vasundhara-v.volam@broadcom.com>
Sun, 5 May 2019 11:17:00 +0000 (07:17 -0400)
committerDavid S. Miller <davem@davemloft.net>
Mon, 6 May 2019 04:42:17 +0000 (21:42 -0700)
Gather periodic PCIe statistics for ethtool -S.

Signed-off-by: Vasundhara Volam <vasundhara-v.volam@broadcom.com>
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 1fb6d5eb3cc3a81477a6037be408ff937fd6ecbd..b7a600564a1666f57c70314cfbcdebb53db6e8cf 100644 (file)
@@ -3396,6 +3396,12 @@ static void bnxt_free_port_stats(struct bnxt *bp)
                                  bp->hw_rx_port_stats_ext_map);
                bp->hw_rx_port_stats_ext = NULL;
        }
+
+       if (bp->hw_pcie_stats) {
+               dma_free_coherent(&pdev->dev, sizeof(struct pcie_ctx_hw_stats),
+                                 bp->hw_pcie_stats, bp->hw_pcie_stats_map);
+               bp->hw_pcie_stats = NULL;
+       }
 }
 
 static void bnxt_free_ring_stats(struct bnxt *bp)
@@ -3477,7 +3483,7 @@ alloc_ext_stats:
 
 alloc_tx_ext_stats:
        if (bp->hw_tx_port_stats_ext)
-               return 0;
+               goto alloc_pcie_stats;
 
        if (bp->hwrm_spec_code >= 0x10902) {
                bp->hw_tx_port_stats_ext =
@@ -3487,6 +3493,19 @@ alloc_tx_ext_stats:
                                           GFP_KERNEL);
        }
        bp->flags |= BNXT_FLAG_PORT_STATS_EXT;
+
+alloc_pcie_stats:
+       if (bp->hw_pcie_stats ||
+           !(bp->fw_cap & BNXT_FW_CAP_PCIE_STATS_SUPPORTED))
+               return 0;
+
+       bp->hw_pcie_stats =
+               dma_alloc_coherent(&pdev->dev, sizeof(struct pcie_ctx_hw_stats),
+                                  &bp->hw_pcie_stats_map, GFP_KERNEL);
+       if (!bp->hw_pcie_stats)
+               return 0;
+
+       bp->flags |= BNXT_FLAG_PCIE_STATS;
        return 0;
 }
 
@@ -6505,6 +6524,8 @@ static int __bnxt_hwrm_func_qcaps(struct bnxt *bp)
                bp->flags |= BNXT_FLAG_ROCEV1_CAP;
        if (flags & FUNC_QCAPS_RESP_FLAGS_ROCE_V2_SUPPORTED)
                bp->flags |= BNXT_FLAG_ROCEV2_CAP;
+       if (flags & FUNC_QCAPS_RESP_FLAGS_PCIE_STATS_SUPPORTED)
+               bp->fw_cap |= BNXT_FW_CAP_PCIE_STATS_SUPPORTED;
 
        bp->tx_push_thresh = 0;
        if (flags & FUNC_QCAPS_RESP_FLAGS_PUSH_MODE_SUPPORTED)
@@ -6805,6 +6826,19 @@ static int bnxt_hwrm_port_qstats_ext(struct bnxt *bp)
        return rc;
 }
 
+static int bnxt_hwrm_pcie_qstats(struct bnxt *bp)
+{
+       struct hwrm_pcie_qstats_input req = {0};
+
+       if (!(bp->flags & BNXT_FLAG_PCIE_STATS))
+               return 0;
+
+       bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_PCIE_QSTATS, -1, -1);
+       req.pcie_stat_size = cpu_to_le16(sizeof(struct pcie_ctx_hw_stats));
+       req.pcie_stat_host_addr = cpu_to_le64(bp->hw_pcie_stats_map);
+       return hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
+}
+
 static void bnxt_hwrm_free_tunnel_ports(struct bnxt *bp)
 {
        if (bp->vxlan_port_cnt) {
@@ -9395,6 +9429,7 @@ static void bnxt_sp_task(struct work_struct *work)
        if (test_and_clear_bit(BNXT_PERIODIC_STATS_SP_EVENT, &bp->sp_event)) {
                bnxt_hwrm_port_qstats(bp);
                bnxt_hwrm_port_qstats_ext(bp);
+               bnxt_hwrm_pcie_qstats(bp);
        }
 
        if (test_and_clear_bit(BNXT_LINK_CHNG_SP_EVENT, &bp->sp_event)) {
index cf81ace7a6e624db540a28e9f981f102074a8f29..178ece3117801d47ccdbf2be3d82a4cf8ccd94ce 100644 (file)
@@ -1354,6 +1354,7 @@ struct bnxt {
        #define BNXT_FLAG_DIM           0x2000000
        #define BNXT_FLAG_ROCE_MIRROR_CAP       0x4000000
        #define BNXT_FLAG_PORT_STATS_EXT        0x10000000
+       #define BNXT_FLAG_PCIE_STATS    0x40000000
 
        #define BNXT_FLAG_ALL_CONFIG_FEATS (BNXT_FLAG_TPA |             \
                                            BNXT_FLAG_RFS |             \
@@ -1480,6 +1481,7 @@ struct bnxt {
        #define BNXT_FW_CAP_KONG_MB_CHNL                0x00000080
        #define BNXT_FW_CAP_OVS_64BIT_HANDLE            0x00000400
        #define BNXT_FW_CAP_TRUSTED_VF                  0x00000800
+       #define BNXT_FW_CAP_PCIE_STATS_SUPPORTED        0x00020000
 
 #define BNXT_NEW_RM(bp)                ((bp)->fw_cap & BNXT_FW_CAP_NEW_RM)
        u32                     hwrm_spec_code;
@@ -1498,10 +1500,12 @@ struct bnxt {
        struct tx_port_stats    *hw_tx_port_stats;
        struct rx_port_stats_ext        *hw_rx_port_stats_ext;
        struct tx_port_stats_ext        *hw_tx_port_stats_ext;
+       struct pcie_ctx_hw_stats        *hw_pcie_stats;
        dma_addr_t              hw_rx_port_stats_map;
        dma_addr_t              hw_tx_port_stats_map;
        dma_addr_t              hw_rx_port_stats_ext_map;
        dma_addr_t              hw_tx_port_stats_ext_map;
+       dma_addr_t              hw_pcie_stats_map;
        int                     hw_port_stats_size;
        u16                     fw_rx_stats_ext_size;
        u16                     fw_tx_stats_ext_size;
@@ -1634,6 +1638,9 @@ struct bnxt {
 #define BNXT_TX_STATS_EXT_OFFSET(counter)              \
        (offsetof(struct tx_port_stats_ext, counter) / 8)
 
+#define BNXT_PCIE_STATS_OFFSET(counter)                        \
+       (offsetof(struct pcie_ctx_hw_stats, counter) / 8)
+
 #define I2C_DEV_ADDR_A0                                0xa0
 #define I2C_DEV_ADDR_A2                                0xa2
 #define SFF_DIAG_SUPPORT_OFFSET                        0x5c
index a3e6a7d209f9921ebb98a48bda2f5e6da0f2465d..bdd9d16ede2832ec934367b7bede90648b81ebb2 100644 (file)
@@ -235,6 +235,9 @@ reset_coalesce:
        BNXT_TX_STATS_PRI_ENTRY(counter, 6),            \
        BNXT_TX_STATS_PRI_ENTRY(counter, 7)
 
+#define BNXT_PCIE_STATS_ENTRY(counter) \
+       { BNXT_PCIE_STATS_OFFSET(counter), __stringify(counter) }
+
 enum {
        RX_TOTAL_DISCARDS,
        TX_TOTAL_DISCARDS,
@@ -387,6 +390,24 @@ static const struct {
        BNXT_TX_STATS_PRI_ENTRIES(tx_packets),
 };
 
+static const struct {
+       long offset;
+       char string[ETH_GSTRING_LEN];
+} bnxt_pcie_stats_arr[] = {
+       BNXT_PCIE_STATS_ENTRY(pcie_pl_signal_integrity),
+       BNXT_PCIE_STATS_ENTRY(pcie_dl_signal_integrity),
+       BNXT_PCIE_STATS_ENTRY(pcie_tl_signal_integrity),
+       BNXT_PCIE_STATS_ENTRY(pcie_link_integrity),
+       BNXT_PCIE_STATS_ENTRY(pcie_tx_traffic_rate),
+       BNXT_PCIE_STATS_ENTRY(pcie_rx_traffic_rate),
+       BNXT_PCIE_STATS_ENTRY(pcie_tx_dllp_statistics),
+       BNXT_PCIE_STATS_ENTRY(pcie_rx_dllp_statistics),
+       BNXT_PCIE_STATS_ENTRY(pcie_equalization_time),
+       BNXT_PCIE_STATS_ENTRY(pcie_ltssm_histogram[0]),
+       BNXT_PCIE_STATS_ENTRY(pcie_ltssm_histogram[2]),
+       BNXT_PCIE_STATS_ENTRY(pcie_recovery_histogram),
+};
+
 #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                     \
@@ -394,6 +415,7 @@ static const struct {
         ARRAY_SIZE(bnxt_rx_pkts_pri_arr) +     \
         ARRAY_SIZE(bnxt_tx_bytes_pri_arr) +    \
         ARRAY_SIZE(bnxt_tx_pkts_pri_arr))
+#define BNXT_NUM_PCIE_STATS ARRAY_SIZE(bnxt_pcie_stats_arr)
 
 static int bnxt_get_num_stats(struct bnxt *bp)
 {
@@ -411,6 +433,9 @@ static int bnxt_get_num_stats(struct bnxt *bp)
                        num_stats += BNXT_NUM_STATS_PRI;
        }
 
+       if (bp->flags & BNXT_FLAG_PCIE_STATS)
+               num_stats += BNXT_NUM_PCIE_STATS;
+
        return num_stats;
 }
 
@@ -513,6 +538,14 @@ skip_ring_stats:
                        }
                }
        }
+       if (bp->flags & BNXT_FLAG_PCIE_STATS) {
+               __le64 *pcie_stats = (__le64 *)bp->hw_pcie_stats;
+
+               for (i = 0; i < BNXT_NUM_PCIE_STATS; i++, j++) {
+                       buf[j] = le64_to_cpu(*(pcie_stats +
+                                              bnxt_pcie_stats_arr[i].offset));
+               }
+       }
 }
 
 static void bnxt_get_strings(struct net_device *dev, u32 stringset, u8 *buf)
@@ -613,6 +646,12 @@ static void bnxt_get_strings(struct net_device *dev, u32 stringset, u8 *buf)
                                }
                        }
                }
+               if (bp->flags & BNXT_FLAG_PCIE_STATS) {
+                       for (i = 0; i < BNXT_NUM_PCIE_STATS; i++) {
+                               strcpy(buf, bnxt_pcie_stats_arr[i].string);
+                               buf += ETH_GSTRING_LEN;
+                       }
+               }
                break;
        case ETH_SS_TEST:
                if (bp->num_tests)