net: hns3: fix pfc packet number incorrect after querying pfc parameters
authorJie Wang <wangjie125@huawei.com>
Wed, 10 Nov 2021 13:42:51 +0000 (21:42 +0800)
committerDavid S. Miller <davem@davemloft.net>
Wed, 10 Nov 2021 14:20:43 +0000 (14:20 +0000)
Currently, driver will send command to firmware to query pfc packet number
when user uses dcb tool to get pfc parameters. However, the periodic
service task will also periodically query and record MAC statistics,
including pfc packet number.

As the hardware registers of statistics is cleared after reading, it will
cause pfc packet number of MAC statistics are not correct after using dcb
tool to get pfc parameters.

To fix this problem, when user uses dcb tool to get pfc parameters, driver
updates MAC statistics firstly and then get pfc packet number from MAC
statistics.

Fixes: 64fd2300fcc1 ("net: hns3: add support for querying pfc puase packets statistic")
Signed-off-by: Jie Wang <wangjie125@huawei.com>
Signed-off-by: Guangbin Huang <huangguangbin2@huawei.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_dcb.c
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.h

index 91cb578..90013c1 100644 (file)
@@ -286,28 +286,24 @@ err_out:
 
 static int hclge_ieee_getpfc(struct hnae3_handle *h, struct ieee_pfc *pfc)
 {
-       u64 requests[HNAE3_MAX_TC], indications[HNAE3_MAX_TC];
        struct hclge_vport *vport = hclge_get_vport(h);
        struct hclge_dev *hdev = vport->back;
        int ret;
-       u8 i;
 
        memset(pfc, 0, sizeof(*pfc));
        pfc->pfc_cap = hdev->pfc_max;
        pfc->pfc_en = hdev->tm_info.pfc_en;
 
-       ret = hclge_pfc_tx_stats_get(hdev, requests);
-       if (ret)
+       ret = hclge_mac_update_stats(hdev);
+       if (ret) {
+               dev_err(&hdev->pdev->dev,
+                       "failed to update MAC stats, ret = %d.\n", ret);
                return ret;
+       }
 
-       ret = hclge_pfc_rx_stats_get(hdev, indications);
-       if (ret)
-               return ret;
+       hclge_pfc_tx_stats_get(hdev, pfc->requests);
+       hclge_pfc_rx_stats_get(hdev, pfc->indications);
 
-       for (i = 0; i < HCLGE_MAX_TC_NUM; i++) {
-               pfc->requests[i] = requests[i];
-               pfc->indications[i] = indications[i];
-       }
        return 0;
 }
 
index 0fc2b81..21aec4e 100644 (file)
@@ -26,8 +26,6 @@
 #include "hclge_devlink.h"
 
 #define HCLGE_NAME                     "hclge"
-#define HCLGE_STATS_READ(p, offset) (*(u64 *)((u8 *)(p) + (offset)))
-#define HCLGE_MAC_STATS_FIELD_OFF(f) (offsetof(struct hclge_mac_stats, f))
 
 #define HCLGE_BUF_SIZE_UNIT    256U
 #define HCLGE_BUF_MUL_BY       2
@@ -587,7 +585,7 @@ static int hclge_mac_query_reg_num(struct hclge_dev *hdev, u32 *reg_num)
        return 0;
 }
 
-static int hclge_mac_update_stats(struct hclge_dev *hdev)
+int hclge_mac_update_stats(struct hclge_dev *hdev)
 {
        /* The firmware supports the new statistics acquisition method */
        if (hdev->ae_dev->dev_specs.mac_stats_num)
index 2101377..3c95c95 100644 (file)
@@ -852,6 +852,9 @@ struct hclge_vf_vlan_cfg {
                (y) = (_k_ ^ ~_v_) & (_k_); \
        } while (0)
 
+#define HCLGE_MAC_STATS_FIELD_OFF(f) (offsetof(struct hclge_mac_stats, f))
+#define HCLGE_STATS_READ(p, offset) (*(u64 *)((u8 *)(p) + (offset)))
+
 #define HCLGE_MAC_TNL_LOG_SIZE 8
 #define HCLGE_VPORT_NUM 256
 struct hclge_dev {
@@ -1166,4 +1169,5 @@ void hclge_inform_vf_promisc_info(struct hclge_vport *vport);
 int hclge_dbg_dump_rst_info(struct hclge_dev *hdev, char *buf, int len);
 int hclge_push_vf_link_status(struct hclge_vport *vport);
 int hclge_enable_vport_vlan_filter(struct hclge_vport *vport, bool request_en);
+int hclge_mac_update_stats(struct hclge_dev *hdev);
 #endif
index 95074e9..a50e2ed 100644 (file)
@@ -113,50 +113,50 @@ static int hclge_shaper_para_calc(u32 ir, u8 shaper_level,
        return 0;
 }
 
-static int hclge_pfc_stats_get(struct hclge_dev *hdev,
-                              enum hclge_opcode_type opcode, u64 *stats)
-{
-       struct hclge_desc desc[HCLGE_TM_PFC_PKT_GET_CMD_NUM];
-       int ret, i, j;
-
-       if (!(opcode == HCLGE_OPC_QUERY_PFC_RX_PKT_CNT ||
-             opcode == HCLGE_OPC_QUERY_PFC_TX_PKT_CNT))
-               return -EINVAL;
-
-       for (i = 0; i < HCLGE_TM_PFC_PKT_GET_CMD_NUM - 1; i++) {
-               hclge_cmd_setup_basic_desc(&desc[i], opcode, true);
-               desc[i].flag |= cpu_to_le16(HCLGE_CMD_FLAG_NEXT);
-       }
-
-       hclge_cmd_setup_basic_desc(&desc[i], opcode, true);
+static const u16 hclge_pfc_tx_stats_offset[] = {
+       HCLGE_MAC_STATS_FIELD_OFF(mac_tx_pfc_pri0_pkt_num),
+       HCLGE_MAC_STATS_FIELD_OFF(mac_tx_pfc_pri1_pkt_num),
+       HCLGE_MAC_STATS_FIELD_OFF(mac_tx_pfc_pri2_pkt_num),
+       HCLGE_MAC_STATS_FIELD_OFF(mac_tx_pfc_pri3_pkt_num),
+       HCLGE_MAC_STATS_FIELD_OFF(mac_tx_pfc_pri4_pkt_num),
+       HCLGE_MAC_STATS_FIELD_OFF(mac_tx_pfc_pri5_pkt_num),
+       HCLGE_MAC_STATS_FIELD_OFF(mac_tx_pfc_pri6_pkt_num),
+       HCLGE_MAC_STATS_FIELD_OFF(mac_tx_pfc_pri7_pkt_num)
+};
 
-       ret = hclge_cmd_send(&hdev->hw, desc, HCLGE_TM_PFC_PKT_GET_CMD_NUM);
-       if (ret)
-               return ret;
+static const u16 hclge_pfc_rx_stats_offset[] = {
+       HCLGE_MAC_STATS_FIELD_OFF(mac_rx_pfc_pri0_pkt_num),
+       HCLGE_MAC_STATS_FIELD_OFF(mac_rx_pfc_pri1_pkt_num),
+       HCLGE_MAC_STATS_FIELD_OFF(mac_rx_pfc_pri2_pkt_num),
+       HCLGE_MAC_STATS_FIELD_OFF(mac_rx_pfc_pri3_pkt_num),
+       HCLGE_MAC_STATS_FIELD_OFF(mac_rx_pfc_pri4_pkt_num),
+       HCLGE_MAC_STATS_FIELD_OFF(mac_rx_pfc_pri5_pkt_num),
+       HCLGE_MAC_STATS_FIELD_OFF(mac_rx_pfc_pri6_pkt_num),
+       HCLGE_MAC_STATS_FIELD_OFF(mac_rx_pfc_pri7_pkt_num)
+};
 
-       for (i = 0; i < HCLGE_TM_PFC_PKT_GET_CMD_NUM; i++) {
-               struct hclge_pfc_stats_cmd *pfc_stats =
-                               (struct hclge_pfc_stats_cmd *)desc[i].data;
+static void hclge_pfc_stats_get(struct hclge_dev *hdev, bool tx, u64 *stats)
+{
+       const u16 *offset;
+       int i;
 
-               for (j = 0; j < HCLGE_TM_PFC_NUM_GET_PER_CMD; j++) {
-                       u32 index = i * HCLGE_TM_PFC_PKT_GET_CMD_NUM + j;
+       if (tx)
+               offset = hclge_pfc_tx_stats_offset;
+       else
+               offset = hclge_pfc_rx_stats_offset;
 
-                       if (index < HCLGE_MAX_TC_NUM)
-                               stats[index] =
-                                       le64_to_cpu(pfc_stats->pkt_num[j]);
-               }
-       }
-       return 0;
+       for (i = 0; i < HCLGE_MAX_TC_NUM; i++)
+               stats[i] = HCLGE_STATS_READ(&hdev->mac_stats, offset[i]);
 }
 
-int hclge_pfc_rx_stats_get(struct hclge_dev *hdev, u64 *stats)
+void hclge_pfc_rx_stats_get(struct hclge_dev *hdev, u64 *stats)
 {
-       return hclge_pfc_stats_get(hdev, HCLGE_OPC_QUERY_PFC_RX_PKT_CNT, stats);
+       hclge_pfc_stats_get(hdev, false, stats);
 }
 
-int hclge_pfc_tx_stats_get(struct hclge_dev *hdev, u64 *stats)
+void hclge_pfc_tx_stats_get(struct hclge_dev *hdev, u64 *stats)
 {
-       return hclge_pfc_stats_get(hdev, HCLGE_OPC_QUERY_PFC_TX_PKT_CNT, stats);
+       hclge_pfc_stats_get(hdev, true, stats);
 }
 
 int hclge_mac_pause_en_cfg(struct hclge_dev *hdev, bool tx, bool rx)
index 2ee9b79..1db7f40 100644 (file)
@@ -228,8 +228,8 @@ int hclge_tm_dwrr_cfg(struct hclge_dev *hdev);
 int hclge_tm_init_hw(struct hclge_dev *hdev, bool init);
 int hclge_mac_pause_en_cfg(struct hclge_dev *hdev, bool tx, bool rx);
 int hclge_pause_addr_cfg(struct hclge_dev *hdev, const u8 *mac_addr);
-int hclge_pfc_rx_stats_get(struct hclge_dev *hdev, u64 *stats);
-int hclge_pfc_tx_stats_get(struct hclge_dev *hdev, u64 *stats);
+void hclge_pfc_rx_stats_get(struct hclge_dev *hdev, u64 *stats);
+void hclge_pfc_tx_stats_get(struct hclge_dev *hdev, u64 *stats);
 int hclge_tm_qs_shaper_cfg(struct hclge_vport *vport, int max_tx_rate);
 int hclge_tm_get_qset_num(struct hclge_dev *hdev, u16 *qset_num);
 int hclge_tm_get_pri_num(struct hclge_dev *hdev, u8 *pri_num);