提交 bf0a4444 编写于 作者: J Jie Wang 提交者: Zheng Zengkai

net: hns3: fix pfc packet number incorrect after querying pfc parameters

mainline inclusion
from mainline-master
commit 0b653a81
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/I4I7P7
CVE: NA

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=0b653a81a26d

----------------------------------------------------------------------

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: 64fd2300 ("net: hns3: add support for querying pfc puase packets statistic")
Signed-off-by: NJie Wang <wangjie125@huawei.com>
Signed-off-by: NGuangbin Huang <huangguangbin2@huawei.com>
Signed-off-by: NDavid S. Miller <davem@davemloft.net>
Reviewed-by: NYongxin Li <liyongxin1@huawei.com>
Signed-off-by: NJunxin Chen <chenjunxin1@huawei.com>
Signed-off-by: NZheng Zengkai <zhengzengkai@huawei.com>
上级 62583337
......@@ -286,28 +286,24 @@ static int hclge_ieee_setets(struct hnae3_handle *h, struct ieee_ets *ets)
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;
}
......
......@@ -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)
......
......@@ -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
......@@ -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)
......
......@@ -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);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册