提交 754b9174 编写于 作者: G Guangbin Huang 提交者: Zheng Zengkai

net: hns3: modify mac statistics update process for compatibility

mainline inclusion
from mainline-master
commit 0bd7e894
category: feature
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=0bd7e894dffa

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

After querying mac statistics from firmware, driver copies data from
descriptors to struct mac_stats of hdev, and the number of copied data
is just according to the register number queried from firmware. There is
a problem that if the register number queried from firmware is larger
than data number of struct mac_stats, it will cause a copy overflow.

So if the firmware adds more mac statistics in later version, it is not
compatible with driver of old version.

To fix this problem, the number of copied data needs to be used the
minimum value between the register number queried from firmware and
data number of struct mac_stats.

The first descriptor has three data and there is one reserved, to
optimize the copy process, add this reserverd data to struct mac_stats.
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>
上级 db2998ba
...@@ -451,8 +451,9 @@ static int hclge_mac_update_stats_defective(struct hclge_dev *hdev) ...@@ -451,8 +451,9 @@ static int hclge_mac_update_stats_defective(struct hclge_dev *hdev)
u64 *data = (u64 *)(&hdev->mac_stats); u64 *data = (u64 *)(&hdev->mac_stats);
struct hclge_desc desc[HCLGE_MAC_CMD_NUM]; struct hclge_desc desc[HCLGE_MAC_CMD_NUM];
__le64 *desc_data; __le64 *desc_data;
int i, k, n; u32 data_size;
int ret; int ret;
u32 i;
hclge_cmd_setup_basic_desc(&desc[0], HCLGE_OPC_STATS_MAC, true); hclge_cmd_setup_basic_desc(&desc[0], HCLGE_OPC_STATS_MAC, true);
ret = hclge_cmd_send(&hdev->hw, desc, HCLGE_MAC_CMD_NUM); ret = hclge_cmd_send(&hdev->hw, desc, HCLGE_MAC_CMD_NUM);
...@@ -463,33 +464,36 @@ static int hclge_mac_update_stats_defective(struct hclge_dev *hdev) ...@@ -463,33 +464,36 @@ static int hclge_mac_update_stats_defective(struct hclge_dev *hdev)
return ret; return ret;
} }
for (i = 0; i < HCLGE_MAC_CMD_NUM; i++) { /* The first desc has a 64-bit header, so data size need to minus 1 */
/* for special opcode 0032, only the first desc has the head */ data_size = sizeof(desc) / (sizeof(u64)) - 1;
if (unlikely(i == 0)) {
desc_data = (__le64 *)(&desc[i].data[0]);
n = HCLGE_RD_FIRST_STATS_NUM;
} else {
desc_data = (__le64 *)(&desc[i]);
n = HCLGE_RD_OTHER_STATS_NUM;
}
for (k = 0; k < n; k++) { desc_data = (__le64 *)(&desc[0].data[0]);
for (i = 0; i < data_size; i++) {
/* data memory is continuous becase only the first desc has a
* header in this command
*/
*data += le64_to_cpu(*desc_data); *data += le64_to_cpu(*desc_data);
data++; data++;
desc_data++; desc_data++;
} }
}
return 0; return 0;
} }
static int hclge_mac_update_stats_complete(struct hclge_dev *hdev, u32 desc_num) static int hclge_mac_update_stats_complete(struct hclge_dev *hdev, u32 reg_num)
{ {
#define HCLGE_REG_NUM_PER_DESC 4
u64 *data = (u64 *)(&hdev->mac_stats); u64 *data = (u64 *)(&hdev->mac_stats);
struct hclge_desc *desc; struct hclge_desc *desc;
__le64 *desc_data; __le64 *desc_data;
u16 i, k, n; u32 data_size;
u32 desc_num;
int ret; int ret;
u32 i;
/* The first desc has a 64-bit header, so need to consider it */
desc_num = reg_num / HCLGE_REG_NUM_PER_DESC + 1;
/* This may be called inside atomic sections, /* This may be called inside atomic sections,
* so GFP_ATOMIC is more suitalbe here * so GFP_ATOMIC is more suitalbe here
...@@ -505,62 +509,58 @@ static int hclge_mac_update_stats_complete(struct hclge_dev *hdev, u32 desc_num) ...@@ -505,62 +509,58 @@ static int hclge_mac_update_stats_complete(struct hclge_dev *hdev, u32 desc_num)
return ret; return ret;
} }
for (i = 0; i < desc_num; i++) { data_size = min_t(u32, sizeof(hdev->mac_stats) / sizeof(u64), reg_num);
/* for special opcode 0034, only the first desc has the head */
if (i == 0) {
desc_data = (__le64 *)(&desc[i].data[0]);
n = HCLGE_RD_FIRST_STATS_NUM;
} else {
desc_data = (__le64 *)(&desc[i]);
n = HCLGE_RD_OTHER_STATS_NUM;
}
for (k = 0; k < n; k++) { desc_data = (__le64 *)(&desc[0].data[0]);
for (i = 0; i < data_size; i++) {
/* data memory is continuous becase only the first desc has a
* header in this command
*/
*data += le64_to_cpu(*desc_data); *data += le64_to_cpu(*desc_data);
data++; data++;
desc_data++; desc_data++;
} }
}
kfree(desc); kfree(desc);
return 0; return 0;
} }
static int hclge_mac_query_reg_num(struct hclge_dev *hdev, u32 *desc_num) static int hclge_mac_query_reg_num(struct hclge_dev *hdev, u32 *reg_num)
{ {
struct hclge_desc desc; struct hclge_desc desc;
__le32 *desc_data;
u32 reg_num;
int ret; int ret;
hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_QUERY_MAC_REG_NUM, true); hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_QUERY_MAC_REG_NUM, true);
ret = hclge_cmd_send(&hdev->hw, &desc, 1); ret = hclge_cmd_send(&hdev->hw, &desc, 1);
if (ret) if (ret) {
dev_err(&hdev->pdev->dev,
"failed to query mac statistic reg number, ret = %d\n",
ret);
return ret; return ret;
}
desc_data = (__le32 *)(&desc.data[0]); *reg_num = le32_to_cpu(desc.data[0]);
reg_num = le32_to_cpu(*desc_data); if (*reg_num == 0) {
dev_err(&hdev->pdev->dev,
*desc_num = 1 + ((reg_num - 3) >> 2) + "mac statistic reg number is invalid!\n");
(u32)(((reg_num - 3) & 0x3) ? 1 : 0); return -ENODATA;
}
return 0; return 0;
} }
static int hclge_mac_update_stats(struct hclge_dev *hdev) static int hclge_mac_update_stats(struct hclge_dev *hdev)
{ {
u32 desc_num; u32 reg_num;
int ret; int ret;
ret = hclge_mac_query_reg_num(hdev, &desc_num); ret = hclge_mac_query_reg_num(hdev, &reg_num);
/* The firmware supports the new statistics acquisition method */ /* The firmware supports the new statistics acquisition method */
if (!ret) if (!ret)
ret = hclge_mac_update_stats_complete(hdev, desc_num); ret = hclge_mac_update_stats_complete(hdev, reg_num);
else if (ret == -EOPNOTSUPP) else if (ret == -EOPNOTSUPP)
ret = hclge_mac_update_stats_defective(hdev); ret = hclge_mac_update_stats_defective(hdev);
else
dev_err(&hdev->pdev->dev, "query mac reg num fail!\n");
return ret; return ret;
} }
......
...@@ -412,6 +412,7 @@ struct hclge_comm_stats_str { ...@@ -412,6 +412,7 @@ struct hclge_comm_stats_str {
struct hclge_mac_stats { struct hclge_mac_stats {
u64 mac_tx_mac_pause_num; u64 mac_tx_mac_pause_num;
u64 mac_rx_mac_pause_num; u64 mac_rx_mac_pause_num;
u64 rsv0;
u64 mac_tx_pfc_pri0_pkt_num; u64 mac_tx_pfc_pri0_pkt_num;
u64 mac_tx_pfc_pri1_pkt_num; u64 mac_tx_pfc_pri1_pkt_num;
u64 mac_tx_pfc_pri2_pkt_num; u64 mac_tx_pfc_pri2_pkt_num;
...@@ -448,7 +449,7 @@ struct hclge_mac_stats { ...@@ -448,7 +449,7 @@ struct hclge_mac_stats {
u64 mac_tx_1519_2047_oct_pkt_num; u64 mac_tx_1519_2047_oct_pkt_num;
u64 mac_tx_2048_4095_oct_pkt_num; u64 mac_tx_2048_4095_oct_pkt_num;
u64 mac_tx_4096_8191_oct_pkt_num; u64 mac_tx_4096_8191_oct_pkt_num;
u64 rsv0; u64 rsv1;
u64 mac_tx_8192_9216_oct_pkt_num; u64 mac_tx_8192_9216_oct_pkt_num;
u64 mac_tx_9217_12287_oct_pkt_num; u64 mac_tx_9217_12287_oct_pkt_num;
u64 mac_tx_12288_16383_oct_pkt_num; u64 mac_tx_12288_16383_oct_pkt_num;
...@@ -475,7 +476,7 @@ struct hclge_mac_stats { ...@@ -475,7 +476,7 @@ struct hclge_mac_stats {
u64 mac_rx_1519_2047_oct_pkt_num; u64 mac_rx_1519_2047_oct_pkt_num;
u64 mac_rx_2048_4095_oct_pkt_num; u64 mac_rx_2048_4095_oct_pkt_num;
u64 mac_rx_4096_8191_oct_pkt_num; u64 mac_rx_4096_8191_oct_pkt_num;
u64 rsv1; u64 rsv2;
u64 mac_rx_8192_9216_oct_pkt_num; u64 mac_rx_8192_9216_oct_pkt_num;
u64 mac_rx_9217_12287_oct_pkt_num; u64 mac_rx_9217_12287_oct_pkt_num;
u64 mac_rx_12288_16383_oct_pkt_num; u64 mac_rx_12288_16383_oct_pkt_num;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册